PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.1
6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 All 155 releases
← All changes | modules/api-backups/classes/class-api-backups-3rd-party.php +4921 -3982 5.0.2 → 6.2.1 View file →
@@ -10,9 +10,15 @@
10 10
11 11 use WP_Error;
12 12 use MainWP\Dashboard\MainWP_DB;
13 13 use MainWP\Dashboard\MainWP_Extensions_Handler;
14 +use MainWP\Dashboard\MainWP_Site_Open;
14 15
16 +// Exit if accessed directly.
17 +if ( ! defined( 'ABSPATH' ) ) {
18 + exit;
19 +}
20 +
15 21 /**
16 22 * Class Api_Backups_3rd_Party
17 23 *
18 24 * This class is responsible for handling the 3rd party API requests for each available backup provider.
@@ -20,4520 +26,5453 @@
20 26 * @package MainWP\Dashboard
21 27 *
22 28 * @version 5.0
23 29 */
24 -class Api_Backups_3rd_Party {
30 +class Api_Backups_3rd_Party { //phpcs:ignore -- NOSONAR - multi methods.
25 31
26 - // phpcs:disable WordPress.DB.RestrictedFunctions, Generic.Metrics.CyclomaticComplexity, WordPress.WP.AlternativeFunctions, WordPress.PHP.NoSilencedErrors -- Using cURL functions.
32 + // phpcs:disable WordPress.DB.RestrictedFunctions, Generic.Metrics.CyclomaticComplexity, WordPress.WP.AlternativeFunctions, WordPress.PHP.NoSilencedErrors -- Using cURL functions.
27 33
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 + const CLOUDWAYS_API_URL = 'https://api.cloudways.com/api/v2';
34 35
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 - }
36 + /**
37 + * Public static variable to hold the single instance of the class.
38 + *
39 + * @var mixed Default null
40 + */
41 + protected static $instance = null;
49 42
50 43
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 - }
44 + /**
45 + * Public static variable to hold the saved access token value.
46 + *
47 + * @var mixed Default null
48 + */
49 + protected static $access_token = null;
61 50
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 - }
51 + /**
52 + * Public static variable.
53 + */
54 + const OPERATION = '/operation/'; // to clean code.
71 55
72 - /**
73 - * Admin init.
74 - */
75 - public function admin_init() {
76 - // Admin Init.
77 - }
56 + /**
57 + * Public static variable.
58 + */
59 + const SNAPSHOTS = '/snapshots/'; // to clean code.
78 60
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' ) );
61 + /**
62 + * Public static variable.
63 + */
64 + const INSTANCES = '/instances/'; // to clean code.
90 65
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' ) );
66 + /**
67 + * Public static variable.
68 + */
69 + const DROPLETS = '/droplets/'; // to clean code.
98 70
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' ) );
71 + /**
72 + * Method instance()
73 + *
74 + * Create a public static instance.
75 + *
76 + * @static
77 + * @return Api_Backups_3rd_Party
78 + */
79 + public static function instance() {
80 + if ( null === static::$instance ) {
81 + static::$instance = new self();
82 + }
83 + return static::$instance;
84 + }
105 85
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 86
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' ) );
87 + /**
88 + * Method get_class_name()
89 + *
90 + * Get class name.
91 + *
92 + * @return string __CLASS__ Class name.
93 + */
94 + public static function get_class_name() {
95 + return __CLASS__;
96 + }
119 97
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' ) );
98 + /**
99 + * Api_Backups_3rd_Party Constructor.
100 + *
101 + * Runs each time the class is called.
102 + */
103 + public function __construct() {
104 + // Initiate admin_init() function.
105 + add_action( 'admin_init', array( &$this, 'admin_init' ) );
106 + }
131 107
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' ) );
108 + /**
109 + * Admin init.
110 + */
111 + public function admin_init() {
112 + // Admin Init.
113 + }
137 114
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' ) );.
115 + /**
116 + * Init ajax actions.
117 + */
118 + public function init_ajax_actions() {
119 + // Cloudways Ajax.
120 + do_action( 'mainwp_ajax_add_action', 'cloudways_action_backup', array( &$this, 'ajax_cloudways_action_backup' ) );
121 + do_action( 'mainwp_ajax_add_action', 'cloudways_action_individual_backup', array( &$this, 'ajax_cloudways_action_individual_backup' ) );
122 + do_action( 'mainwp_ajax_add_action', 'cloudways_action_update_ids', array( &$this, 'ajax_cloudways_action_update_ids' ) );
123 + do_action( 'mainwp_ajax_add_action', 'cloudways_action_refresh_available_backups', array( &$this, 'cloudways_action_refresh_available_backups' ) );
124 + do_action( 'mainwp_ajax_add_action', 'cloudways_action_restore_backup', array( &$this, 'cloudways_action_restore_backup' ) );
125 + do_action( 'mainwp_ajax_add_action', 'cloudways_action_delete_backup', array( &$this, 'cloudways_action_delete_backup' ) );
142 126
143 - // Backup selected sites.
144 - do_action( 'mainwp_ajax_add_action', 'action_backup_selected_sites', array( &$this, 'action_backup_selected_sites' ) );
127 + // GridPane Ajax.
128 + do_action( 'mainwp_ajax_add_action', 'gridpane_action_create_backup', array( &$this, 'ajax_gridpane_action_create_backup' ) );
129 + do_action( 'mainwp_ajax_add_action', 'gridpane_action_individual_create_backup', array( &$this, 'ajax_gridpane_action_individual_create_backup' ) );
130 + do_action( 'mainwp_ajax_add_action', 'gridpane_action_update_ids', array( &$this, 'ajax_gridpane_action_update_ids' ) );
131 + do_action( 'mainwp_ajax_add_action', 'gridpane_action_refresh_available_backups', array( &$this, 'gridpane_action_refresh_available_backups' ) );
132 + do_action( 'mainwp_ajax_add_action', 'gridpane_action_restore_backup', array( &$this, 'gridpane_action_restore_backup' ) );
133 + do_action( 'mainwp_ajax_add_action', 'gridpane_action_delete_backup', array( &$this, 'gridpane_action_delete_backup' ) );
145 134
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 - }
135 + // Vultr Ajax.
136 + do_action( 'mainwp_ajax_add_action', 'vultr_action_create_snapshot', array( &$this, 'ajax_vultr_action_create_snapshot' ) );
137 + do_action( 'mainwp_ajax_add_action', 'vultr_action_individual_create_snapshot', array( &$this, 'ajax_vultr_action_individual_create_snapshot' ) );
138 + do_action( 'mainwp_ajax_add_action', 'vultr_action_refresh_available_backups', array( &$this, 'vultr_action_refresh_available_backups' ) );
139 + do_action( 'mainwp_ajax_add_action', 'vultr_action_restore_backup', array( &$this, 'ajax_vultr_action_restore_backup' ) );
140 + do_action( 'mainwp_ajax_add_action', 'vultr_action_delete_backup', array( &$this, 'vultr_action_delete_backup' ) );
150 141
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 - }
142 + // Linode Ajax.
143 + do_action( 'mainwp_ajax_add_action', 'linode_action_create_backup', array( &$this, 'ajax_linode_action_create_backup' ) );
144 + do_action( 'mainwp_ajax_add_action', 'linode_action_individual_create_backup', array( &$this, 'ajax_linode_action_individual_create_backup' ) );
145 + do_action( 'mainwp_ajax_add_action', 'linode_action_refresh_available_backups', array( &$this, 'linode_action_refresh_available_backups' ) );
146 + do_action( 'mainwp_ajax_add_action', 'linode_action_restore_backup', array( &$this, 'linode_action_restore_backup' ) );
147 + do_action( 'mainwp_ajax_add_action', 'linode_action_cancel_backups', array( &$this, 'linode_action_cancel_backups' ) );
163 148
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' ); ?>
149 + // DigitalOcean Ajax.
150 + do_action( 'mainwp_ajax_add_action', 'digitalocean_action_create_backup', array( &$this, 'ajax_digitalocean_action_create_backup' ) );
151 + do_action( 'mainwp_ajax_add_action', 'digitalocean_action_individual_create_backup', array( &$this, 'ajax_digitalocean_action_individual_create_backup' ) );
152 + do_action( 'mainwp_ajax_add_action', 'digitalocean_action_refresh_available_backups', array( &$this, 'digitalocean_action_refresh_available_backups' ) );
153 + do_action( 'mainwp_ajax_add_action', 'digitalocean_action_restore_backup', array( &$this, 'digitalocean_action_restore_backup' ) );
154 + do_action( 'mainwp_ajax_add_action', 'digitalocean_action_delete_backup', array( &$this, 'digitalocean_action_delete_backup' ) );
192 155
193 - </div>
194 - <?php
195 - }
156 + // cPanel Ajax.
157 + do_action( 'mainwp_ajax_add_action', 'cpanel_action_refresh_available_backups', array( &$this, 'ajax_cpanel_action_refresh_available_backups' ) );
158 + do_action( 'mainwp_ajax_add_action', 'cpanel_action_create_manual_backup', array( &$this, 'ajax_cpanel_action_create_manual_backup' ) );
159 + do_action( 'mainwp_ajax_add_action', 'cpanel_action_create_wptk_backup', array( &$this, 'ajax_cpanel_action_create_wptk_backup' ) );
160 + do_action( 'mainwp_ajax_add_action', 'cpanel_action_restore_wptk_backup', array( &$this, 'ajax_cpanel_action_restore_wptk_backup' ) );
161 + do_action( 'mainwp_ajax_add_action', 'cpanel_action_delete_wptk_backup', array( &$this, 'ajax_cpanel_action_delete_wptk_backup' ) );
162 + do_action( 'mainwp_ajax_add_action', 'cpanel_action_restore_backup', array( &$this, 'ajax_cpanel_action_restore_backup' ) );
163 + do_action( 'mainwp_ajax_add_action', 'cpanel_action_restore_database_backup', array( &$this, 'ajax_cpanel_action_restore_database_backup' ) );
164 + do_action( 'mainwp_ajax_add_action', 'cpanel_action_restore_manual_backup', array( &$this, 'ajax_cpanel_action_restore_manual_backup' ) );
165 + do_action( 'mainwp_ajax_add_action', 'cpanel_action_create_database_backup', array( &$this, 'ajax_cpanel_action_create_database_backup' ) );
166 + do_action( 'mainwp_ajax_add_action', 'cpanel_action_create_full_backup', array( &$this, 'ajax_cpanel_action_create_full_backup' ) );
196 167
168 + // Plesk Ajax.
169 + do_action( 'mainwp_ajax_add_action', 'plesk_action_refresh_available_backups', array( &$this, 'ajax_plesk_action_refresh_available_backups' ) );
170 + do_action( 'mainwp_ajax_add_action', 'plesk_action_create_backup', array( &$this, 'ajax_plesk_action_create_backup' ) );
171 + do_action( 'mainwp_ajax_add_action', 'plesk_action_restore_backup', array( &$this, 'ajax_plesk_action_restore_backup' ) );
172 + do_action( 'mainwp_ajax_add_action', 'plesk_action_delete_backup', array( &$this, 'ajax_plesk_action_delete_backup' ) );
197 173
198 - /**
199 - * Render the global 3rd party api backups table.
200 - *
201 - * @return void
202 - */
203 - public static function render_api_backups_table() {
174 + // Kinsta Ajax.
175 + do_action( 'mainwp_ajax_add_action', 'kinsta_action_refresh_available_backups', array( &$this, 'ajax_kinsta_action_refresh_available_backups' ) );
176 + do_action( 'mainwp_ajax_add_action', 'kinsta_action_create_backup', array( &$this, 'ajax_kinsta_action_create_backup' ) );
177 + do_action( 'mainwp_ajax_add_action', 'kinsta_action_restore_backup', array( &$this, 'ajax_kinsta_action_restore_backup' ) );
178 + do_action( 'mainwp_ajax_add_action', 'kinsta_action_delete_backup', array( &$this, 'ajax_kinsta_action_delete_backup' ) );
204 179
205 - // Get all Child Sites aloud by user role.
206 - $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
180 + // Backup selected sites.
181 + do_action( 'mainwp_ajax_add_action', 'action_backup_selected_sites', array( &$this, 'action_backup_selected_sites' ) );
207 182
208 - ?>
209 - <?php // Render action notifications. I get replaced by JS. ?>
210 - <div id="mainwp-api-backups-message-zone" class="ui message" style="display: none;">
211 - <i class="icon close"></i>
212 - <div class="content">
213 - <div class="message"></div>
214 - </div>
215 - </div>
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 - */
183 + // Fire off Cloudways & Gridpane ID auto lookup on site addition.
184 + add_action( 'mainwp_added_new_site', array( &$this, 'hook_added_new_site' ), 10, 2 );
185 + }
239 186
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 187
245 - // Check for Plesk and change to WP-Toolkit.
246 - if ( 'Plesk' === $api_provider ) {
247 - $api_provider = 'Plesk (WP Toolkit)';
248 - }
188 + /**
189 + * Hook after new site added.
190 + *
191 + * @param int $id Site id just added.
192 + * @param object $website Site data just added.
193 + *
194 + * @return void
195 + */
196 + public function hook_added_new_site( $id, $website ) {
197 + unset( $id );
198 + $success = $this->fetch_cloudways_settings_for_site( $website );
199 + if ( ! $success ) {
200 + $this->fetch_gridpane_settings_for_site( $website );
201 + }
202 + }
249 203
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 204
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 - }
205 + /**
206 + * Hook after new site added.
207 + *
208 + * @param object $website Site data just added.
209 + *
210 + * @return bool result.
211 + */
212 + public function fetch_cloudways_settings_for_site( $website ) {
260 213
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 - }
214 + if ( empty( $website ) || empty( $website->id ) || empty( $website->url ) ) {
215 + return false;
216 + }
340 217
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.
218 + $url = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', $website->url ) );
347 219
348 - $available_backups = array();
220 + // Fetch Cloudways Server List.
221 + $server_list = static::fetch_cloudways_server_list();
349 222
350 - if ( empty( $website ) ) {
351 - return;
352 - }
223 + /**
224 + * Search $server_list for Child Site app ID & server ID.
225 + *
226 + * Loop through each Server/App & check if app cname / fqdn name matches any Child Site domain name.
227 + * if so, save the server & app ID to that Child Site's options table.
228 + */
229 + if ( ! is_array( $server_list ) ) {
230 + return false;
231 + }
353 232
354 - $website_id = $website['id'];
233 + $found_child_site_id = $website->id;
355 234
356 - /**
357 - * Grab Child Site data needed to display Table.
358 - */
235 + foreach ( $server_list as $server ) {
236 + foreach ( $server->apps as $app ) {
237 + if ( $app->cname === $url || $app->app_fqdn === $url ) { // Check if app fqdn name matches any Child Site domain name, if so, save the server & app ID to that Child Site's options table.
238 + $this->update_3rd_party_cloudways_data( $found_child_site_id, $app );
239 + return true;
240 + }
241 + }
242 + }
359 243
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;
244 + return false;
245 + }
363 246
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' ) );
247 + /**
248 + * Method update_3rd_party_data().
249 + *
250 + * @param int $site_id site id.
251 + * @param object $app app data.
252 + *
253 + * @return void
254 + */
255 + public function update_3rd_party_cloudways_data( $site_id, $app ) {
256 + Api_Backups_Helper::update_website_option( $site_id, 'mainwp_3rd_party_app_id', $app->id );
257 + Api_Backups_Helper::update_website_option( $site_id, 'mainwp_3rd_party_instance_id', $app->server_id );
258 + Api_Backups_Helper::update_website_option( $site_id, 'mainwp_3rd_party_api', 'Cloudways' );
259 + }
366 260
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 261
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 { ?>
262 + /**
263 + * Hook after new site added.
264 + *
265 + * @param object $website Site data just added.
266 + *
267 + * @return bool result.
268 + */
269 + public function fetch_gridpane_settings_for_site( $website ) {
409 270
410 - <?php
411 - $columns = 'one';
412 - if ( 'cpanel' === $backup_api || 'plesk' === $backup_api ) {
413 - $columns = 'two';
414 - }
415 - ?>
416 - <div class="mainwp-sub-header">
417 - <div class="ui grid">
418 - <div class="ui <?php echo esc_html( $columns ); ?> column row">
419 - <div class="middle aligned column ui">
420 - <?php if ( 'cpanel' === $backup_api ) : ?>
421 - <div id="mainwp_api_cpanel_backup_tabs" class="ui top attached tabular menu">
422 - <div class="active item" data-tab="cpanel-native"><i class="fitted cpanel big icon"></i></div>
423 - <div class="item" data-tab="cpanel-wp-toolkit"><i class="fitted wordpress big icon"></i></div><?php //phpcs:ignore -- skip wordpress.?>
424 - </div>
425 - <?php endif; ?>
426 - </div>
427 - <div class="right aligned middle aligned column">
428 - <?php if ( 'cpanel' === $backup_api ) : ?>
429 - <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>
430 - <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>
431 - <?php else : ?>
432 - <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>
433 - <?php endif; ?>
434 - <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>
271 + if ( empty( $website ) || empty( $website->id ) || empty( $website->url ) ) {
272 + return false;
273 + }
435 274
436 - <?php // Render DigitalOcean specific action buttons. ?>
437 - <?php
438 - if ( 'digitalocean' === $backup_api ) {
439 - // Grab Linode instance id.
440 - $digitalocean_droplet_id = Api_Backups_Helper::get_website_options(
441 - $website,
442 - array(
443 - 'mainwp_3rd_party_instance_id',
444 - )
445 - );
446 - $droplet_id = isset( $digitalocean_droplet_id['mainwp_3rd_party_instance_id'] ) ? $digitalocean_droplet_id['mainwp_3rd_party_instance_id'] : null;
447 - ?>
448 - <a href="https://cloud.digitalocean.com/droplets/<?php echo esc_attr( $droplet_id ); ?>/snapshots" target="_blank" class="ui mini button">
449 - <i class="external icon"></i>
450 - <?php esc_html_e( 'View on DigitalOcean', 'mainwp' ); ?>
451 - </a>
452 - <?php } ?>
453 - <?php // Render Linode specific action buttons. ?>
454 - <?php
455 - if ( 'linode' === $backup_api ) {
456 - // Grab Linode instance id.
457 - $linode_instance_id = Api_Backups_Helper::get_website_options(
458 - $website,
459 - array(
460 - 'mainwp_3rd_party_instance_id',
461 - )
462 - );
463 - $instance_id = isset( $linode_instance_id['mainwp_3rd_party_instance_id'] ) ? $linode_instance_id['mainwp_3rd_party_instance_id'] : null;
464 - ?>
465 - <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>
466 - <a href="https://cloud.linode.com/linodes/<?php echo esc_attr( $instance_id ); ?>/backup" target="_blank" class="ui mini button">
467 - <i class="external icon"></i>
468 - <?php esc_html_e( 'View on Akamai (Linode)', 'mainwp' ); ?>
469 - </a>
470 - <?php } ?>
471 - <?php // Render Cloudways specific action buttons. ?>
472 - <?php
473 - if ( 'cloudways' === $backup_api ) {
474 - // Grab Cloudways app id.
475 - $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_app_id' ) );
476 - $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
477 - ?>
478 - <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>
479 - <a href="https://platform.cloudways.com/apps/<?php echo esc_attr( $app_id ); ?>/restore" target="_blank" class="ui mini button">
480 - <i class="external icon"></i>
481 - <?php esc_html_e( 'View on Cloudways', 'mainwp' ); ?>
482 - </a>
483 - <?php } ?>
484 - <?php // Render Vultr specific action buttons. ?>
485 - <?php
486 - if ( 'vultr' === $backup_api ) {
487 - // Grab Vultr Instance id.
488 - $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_instance_id' ) );
489 - $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
490 - ?>
491 - <a href="https://my.vultr.com/subs/?id=<?php echo esc_attr( $instance_id ); ?>#subssnapshots" target="_blank" class="ui mini button">
492 - <i class="external icon"></i>
493 - <?php esc_html_e( 'View on Vultr', 'mainwp' ); ?>
494 - </a>
495 - <?php } ?>
496 - <?php // Render GridPane specific action buttons. ?>
497 - <?php if ( 'gridpane' === $backup_api ) { ?>
498 - <a href="https://my.gridpane.com/sites" target="_blank" class="ui mini button">
499 - <i class="external icon"></i>
500 - <?php esc_html_e( 'View on GridPane', 'mainwp' ); ?>
501 - </a>
502 - <?php } ?>
503 - </div>
504 - </div>
505 - </div>
506 - </div>
507 - <div class="ui segment">
275 + $url = rawurlencode( $website->url );
276 + $strip_protocall = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', urldecode( $url ) ) );
277 + $clean_url = preg_replace( '/^www\./', '', $strip_protocall );
508 278
509 - <?php // Render action notifications. I get replaced by JS. ?>
510 - <div id="mainwp-api-backups-message-zone" class="ui message" style="display: none;">
511 - <i class="icon close"></i>
512 - <div class="content">
513 - <div class="message"></div>
514 - </div>
515 - </div>
279 + // Get Sites list.
280 + $gridpane_list = static::gridpane_get_sites_list( 200 );
516 281
517 - <?php // Render info notifications. ?>
518 - <?php // Render Linode info notifications. ?>
519 - <?php if ( 'linode' === $backup_api ) { ?>
520 - <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message1' ) ) : ?>
521 - <div class="ui info message">
522 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message1"></i>
523 - <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>
524 - </div>
525 - <div class="ui info message">
526 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message1"></i>
527 - <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>
528 - </div>
529 - <?php endif; ?>
530 - <?php } ?>
531 - <?php if ( 'cloudways' === $backup_api ) { ?>
532 - <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message2' ) ) : ?>
533 - <div class="ui info message">
534 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message2"></i>
535 - <div><?php esc_html_e( ' This page allows you to back up and restore your currently available Cloudways backups.', 'mainwp' ); ?></div>
536 - </div>
537 - <div class="ui info message">
538 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message2"></i>
539 - <p><?php esc_html_e( 'Please note that Cloudways does not allow you to delete individual backups.', 'mainwp' ); ?></p>
540 - <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>
541 - <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>
542 - <p><?php esc_html_e( 'This local copy is kept for the first 24 hours, after which it is automatically removed.', 'mainwp' ); ?></p>
543 - </div>
544 - <?php endif; ?>
545 - <?php } ?>
546 - <?php if ( 'digitalocean' === $backup_api ) { ?>
547 - <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message3' ) ) : ?>
548 - <div class="ui info message">
549 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message3"></i>
550 - <div><?php esc_html_e( ' This page allows you to back up and restore your currently available DigitalOcean backups.', 'mainwp' ); ?></div>
551 - </div>
552 - <?php endif; ?>
553 - <?php } ?>
554 - <?php if ( 'gridpane' === $backup_api ) { ?>
555 - <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message4' ) ) : ?>
556 - <div class="ui info message">
557 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message4"></i>
558 - <div><?php esc_html_e( ' This page allows you to back up and restore your currently available GridPane backups.', 'mainwp' ); ?></div>
559 - </div>
560 - <?php endif; ?>
561 - <?php } ?>
562 - <?php if ( 'vultr' === $backup_api ) { ?>
563 - <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message5' ) ) : ?>
564 - <div class="ui info message">
565 - <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message5"></i>
566 - <div><?php esc_html_e( ' This page allows you to back up and restore your currently available Vultr backups.', 'mainwp' ); ?></div>
567 - </div>
568 - <?php endif; ?>
569 - <?php } ?>
282 + // Check for Child Site IP @ each instance. Add to Child Site Options Table.
283 + if ( is_array( $gridpane_list ) ) {
284 + foreach ( $gridpane_list as $gpane_site ) {
285 + if ( $gpane_site->url === $clean_url ) {
286 + // Grab Site options then update Child Site options.
287 + Api_Backups_Helper::update_website_option( $website->id, 'mainwp_3rd_party_instance_id', $gpane_site->id );
288 + Api_Backups_Helper::update_website_option( $website->id, 'mainwp_3rd_party_api', 'GridPane' );
289 + return true;
290 + }
291 + }
292 + }
293 + return false;
294 + }
570 295
571 - <?php // Display Plesk Table. ?>
572 - <?php
573 - if ( 'plesk' === $backup_api ) {
574 - // Grab available cPanel Automatic Backups or set to empty array.
575 - if ( is_object( $available_backups ) && isset( $available_backups->value ) ) {
576 - $available_backups = $available_backups->value;
577 - } else {
578 - $available_backups = array();
579 - }
580 - ?>
581 - <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
582 - <thead>
583 - <tr>
584 - <th><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
585 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
586 - <th class="no-sort collapsing"></th>
587 - <th class="no-sort collapsing"></th>
588 - </tr>
589 - </thead>
590 - <tbody>
591 - <?php foreach ( $available_backups as $backup ) { ?>
592 - <?php
593 - $backup_date = gmdate( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $backup->value->createdAt->value ) );
594 296
595 - $opts = Api_Backups_Helper::get_website_options(
596 - $website['id'],
597 - array(
598 - 'mainwp_plesk_installation_id', // Plesk installation id.
599 - )
600 - );
297 + /**
298 + * Global backup page Action notification handler.
299 + *
300 + * @return void
301 + */
302 + public static function action_notifications() {
303 + if ( isset( $_GET['backup'] ) && ( 'true' === $_GET['backup'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
304 + echo '<div class="ui message green"><i class="icon close"></i> ' . esc_html__( 'All Backups have been created.', 'mainwp' ) . '</div>';
305 + } elseif ( isset( $_GET['backup'] ) && ( 'false' === $_GET['backup'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
306 + echo '<div class="ui message red"><i class="icon close"></i> ' . esc_html__( 'There was an issue with creating your backup.', 'mainwp' ) . '</div>';
307 + }
308 + }
601 309
602 - if ( is_array( $opts ) ) {
603 - $installation_id = $opts['mainwp_plesk_installation_id'] ?? '';
604 - }
605 - ?>
606 - <tr>
607 - <td class="collapsing"><?php esc_html_e( $backup->value->fileName->value ); ?></td>
608 - <td class="collapsing"><?php echo esc_html( $backup_date ); ?></td>
609 - <td></td>
610 - <td class="collapsing right aligned">
611 - <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"
612 - installation_id="<?php echo intval( $installation_id ); ?>"
613 - website_id="<?php echo intval( $website['id'] ); ?>"
614 - backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
615 - data-tooltip="<?php esc_attr_e( 'Restore Backup', 'mainwp' ); ?>"
616 - data-inverted=""
617 - data-position="top center">
618 - <i class="undo icon"></i>
619 - </button>
620 - <?php
621 - /**
622 - * Grab installation domain & build path to download.
623 - * Eg.: /var/www/vhosts/example.com/wordpress-backups/
624 - */
625 - $installation_domain = self::get_plesk_home_dir();
626 - $dirdl = '/var/www/vhosts/' . $installation_domain . '/wordpress-backups/';
627 - ?>
310 + /**
311 + * Render the main api backups page.
312 + *
313 + * @return void
314 + */
315 + public static function render_mainwp_backups_page() {
316 + ?>
317 + <div class="mainwp-sub-header">
318 + <div class="ui grid">
319 + <div class="ui two column row">
320 + <div class="middle aligned column ui">
321 + <button id="action_backup_selected_sites" class="ui green mini button disabled"><?php esc_html_e( 'Backup Selected Sites', 'mainwp' ); ?></button>
322 + </div>
323 + <div class="right aligned middle aligned column">
324 + <a href="admin.php?page=SettingsApiBackups" class="ui mini green basic button"><?php esc_html_e( 'Manage API Backups Settings', 'mainwp' ); ?></a>
325 + </div>
326 + </div>
327 + </div>
328 + </div>
329 + <div class="ui padded segment" id="mainwp-3rd-party-api-backups">
330 + <?php static::action_notifications(); ?>
331 + <?php static::render_api_backups_table( '3rd-party-api-backups' ); ?>
332 + </div>
333 + <?php
334 + }
628 335
629 - <a id="plesk_download_button" class="ui circular mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_downlaod_backup item"
630 - installation_id="<?php echo intval( $installation_id ); ?>"
631 - website_id="<?php echo intval( $website['id'] ); ?>"
632 - backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
633 - 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' ) ); ?>"
634 - data-tooltip="<?php esc_attr_e( 'Download Backup', 'mainwp' ); ?>"
635 - data-inverted=""
636 - data-position="top center"
637 - target="_blank">
638 - <i class="download icon"></i>
639 - </a>
640 - <button id="plesk_delete_button" class="ui circular mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup item"
641 - installation_id="<?php echo intval( $installation_id ); ?>"
642 - website_id="<?php echo intval( $website['id'] ); ?>"
643 - backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
644 - data-tooltip="<?php esc_attr_e( 'Delete Backup', 'mainwp' ); ?>"
645 - data-inverted=""
646 - data-position="top center">
647 - <i class="trash icon"></i>
648 - </button>
649 - </td>
650 - </tr>
651 - <?php } ?>
652 - </tbody>
653 - <tfoot>
654 - <tr>
655 - <th><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
656 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
657 - <th class="no-sort collapsing"></th>
658 - <th class="no-sort collapsing"></th>
659 - </tr>
660 - </tfoot>
661 - </table>
662 - <?php } ?>
663 - <?php // Display cPanel Table. ?>
664 - <?php
665 - if ( 'cpanel' === $backup_api ) {
666 336
667 - // Grab available cPanel Automatic Backups or set to empty array.
668 - if ( is_object( $available_backups ) && isset( $available_backups->data ) ) {
669 - $available_backups_automatic_list = $available_backups->data;
670 - } else {
671 - $available_backups_automatic_list = array();
672 - }
337 + /**
338 + * Render the global 3rd party api backups table.
339 + *
340 + * @return void
341 + */
342 + public static function render_api_backups_table() { //phpcs:ignore -- NOSONAR - complex.
673 343
674 - // Grab available cPanel Manual Backups.
675 - $available_backups_manual_list = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ) );
676 - // Grab Last Backup date UTC.
677 - $last_backup_array = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $backup_api . '_last_backup' ) );
678 - $last_backup_UTC = isset( $last_backup_array[ 'mainwp_3rd_party_' . $backup_api . '_last_backup' ] ) ? $last_backup_array[ 'mainwp_3rd_party_' . $backup_api . '_last_backup' ] : '';
679 - $last_backup = Api_Backups_Utility::format_timestamp( $last_backup_UTC );
344 + // Get all Child Sites aloud by user role.
345 + $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
680 346
681 - // Check if valid JSON or not. If not, then it's a string - do not decode it.
682 - 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' ] ) ) {
683 - json_decode( $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ] );
684 - if ( json_last_error() === JSON_ERROR_NONE ) {
685 - // JSON is valid.
686 - $available_backups_manual_list = json_decode( $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ] );
687 - } else {
688 - // JSON is invalid treat it as a string.
689 - $available_backups_manual_list = $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ];
690 - }
691 - } else {
692 - $available_backups_manual_list = array();
693 - }
347 + ?>
348 + <?php // Render action notifications. I get replaced by JS. ?>
349 + <div id="mainwp-api-backups-message-zone" class="ui message" style="display: none;">
350 + <i class="icon close"></i>
351 + <div class="content">
352 + <div class="message"></div>
353 + </div>
354 + </div>
355 + <table id="mainwp-3rd-party-backups-table" class="ui mainwp-api-backup-table table" style="width:100%">
356 + <thead>
357 + <tr>
358 + <th scope="col" class="no-sort collapsing check-column">
359 + <span class="ui checkbox">
360 + <label for="cb-select-all-top"></label>
361 + <input id="cb-select-all-top" type="checkbox"/>
362 + </span>
363 + </th>
364 + <th scope="col"><?php esc_html_e( 'Site', 'mainwp' ); ?></th>
365 + <th scope="col"><?php esc_html_e( 'API Provider', 'mainwp' ); ?></th>
366 + <th scope="col"><?php esc_html_e( 'Last Manual Backup Date', 'mainwp' ); ?></th>
367 + <th scope="col" class="no-sort collapsing"></th>
368 + </tr>
369 + </thead>
370 + <tbody>
371 + <?php while ( $websites && ( $website = Api_Backups_Helper::fetch_object( $websites ) ) ) { ?>
372 + <?php
373 + /**
374 + * Grab Child Site data needed to display Table.
375 + */
694 376
695 - // Grab available cPanel Manual Database Backups.
696 - $mainwp_3rd_party_cpanel_manual_database_backups = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ) );
377 + // Grab API Provider.
378 + $api_provider_array = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_api' ) );
379 + $api_provider = ( isset( $api_provider_array['mainwp_3rd_party_api'] ) && '' !== $api_provider_array['mainwp_3rd_party_api'] ) ? $api_provider_array['mainwp_3rd_party_api'] : 'None';
380 + $api_provider_options = strtolower( $api_provider );
697 381
698 - // Check if valid JSON or not. If not, then it's a string - do not decode it.
699 - 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' ] ) ) {
700 - json_decode( $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ] );
701 - if ( json_last_error() === JSON_ERROR_NONE ) {
702 - // JSON is valid.
703 - $available_manual_database_backups = json_decode( $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ] );
704 - } else {
705 - // JSON is invalid treat it as a string.
706 - $available_manual_database_backups = $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ];
707 - }
708 - } else {
709 - $available_manual_database_backups = array();
710 - }
711 - ?>
712 - <div class="ui bottom attached active tab" data-tab="cpanel-native">
713 - <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
714 - <thead>
715 - <tr>
716 - <th colspan="4">
717 - <?php esc_html_e( 'Automatic Host Backups', 'mainwp' ); ?>
718 - </th>
719 - </tr>
720 - <tr>
721 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
722 - <th><?php esc_html_e( 'Backup Type', 'mainwp' ); ?></th>
723 - <th><?php esc_html_e( 'Site Path', 'mainwp' ); ?></th>
724 - <th class="no-sort collapsing"></th>
725 - </tr>
726 - </thead>
727 - <tbody>
728 - <?php foreach ( $available_backups_automatic_list as $backup ) { ?>
729 - <tr>
730 - <td><?php esc_html_e( $backup->backupID ); ?></td>
731 - <td><?php esc_html_e( ucfirst( $backup->backupType ), 'mainwp' ); ?></td>
732 - <td><?php echo esc_html_e( $backup->path ); ?></td>
733 - <td>
734 - <a id="cpanel_automatic_backup_button" class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup item"
735 - website_id="<?php echo intval( $website['id'] ); ?>"
736 - backup_type="<?php echo esc_attr( 'automatic' ); ?>"
737 - backup_path="<?php echo esc_attr( $backup->path ); ?>"
738 - backup_name="<?php echo esc_attr( $backup->backupID ); ?>"
739 - href="javascript:void(0)">
740 - <button class="ui right labeled icon button">
741 - <i class="right undo icon"></i>
742 - <?php esc_html_e( 'Restore', 'mainwp' ); ?>
743 - </button>
744 - </a>
745 - </td>
746 - </tr>
747 - <?php } ?>
748 - </tbody>
749 - <tfoot>
750 - <tr>
751 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
752 - <th><?php esc_html_e( 'Backup Type', 'mainwp' ); ?></th>
753 - <th><?php esc_html_e( 'Site Path', 'mainwp' ); ?></th>
754 - <th class="no-sort collapsing"></th>
755 - </tr>
756 - </tfoot>
757 - </table>
758 - <div class="ui divider hidden"></div>
759 - <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
760 - <thead>
761 - <tr>
762 - <th colspan="3">
763 - <div class="ui equal width grid">
764 - <div class="left aligned middle aligned column">
765 - <?php esc_html_e( 'Manual Account Backups', 'mainwp' ); ?>
766 - </div>
767 - <div class="right aligned middle aligned column">
768 - <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>
769 - </div>
770 - </div>
771 - </th>
772 - </tr>
773 - <tr>
774 - <th><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
775 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
776 - <th class="no-sort collapsing"></th>
777 - </tr>
778 - </thead>
779 - <tbody>
780 - <?php foreach ( $available_backups_manual_list as $backup ) { ?>
781 - <?php
782 - $my_unix_timestamp = $backup->timestamp;
783 - $backup_date = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $my_unix_timestamp ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
784 - ?>
785 - <tr>
786 - <td class="collapsing"><?php esc_html_e( $backup->file_name ); ?></td>
787 - <td class="collapsing"><?php esc_html_e( $backup_date ); ?></td>
788 - <td>
789 - <?php
790 - $file_path = $backup->absolute_dir . '/';
791 - ?>
792 - <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">
793 - <button class="ui right labeled icon button">
794 - <i class="right download icon"></i>
795 - <?php echo esc_html__( 'Download', 'mainwp' ); ?>
796 - </button>
797 - </a>
798 - </td>
799 - </tr>
800 - <?php } ?>
801 - </tbody>
802 - <tfoot>
803 - <tr>
804 - <th><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
805 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
806 - <th class="no-sort collapsing"></th>
807 - </tr>
808 - </tfoot>
809 - </table>
810 - <div class="ui divider hidden"></div>
811 - <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
812 - <thead>
813 - <tr>
814 - <th colspan="3">
815 - <div class="ui equal width grid">
816 - <div class="left aligned middle aligned column">
817 - <?php esc_html_e( 'Manual Database Backups', 'mainwp' ); ?>
818 - </div>
819 - <div class="right aligned middle aligned column">
820 - <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>
821 - </div>
822 - </div>
823 - </th>
824 - </tr>
825 - <tr>
826 - <th><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
827 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
828 - <th class="no-sort collapsing"></th>
829 - </tr>
830 - </thead>
831 - <tbody>
832 - <?php foreach ( $available_manual_database_backups as $backup ) { ?>
833 - <?php
834 - $my_unix_timestamp = $backup->timestamp;
835 - $backup_date = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $my_unix_timestamp ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
836 - ?>
837 - <tr>
838 - <td class="collapsing"><?php esc_html_e( $backup->file_name ); ?></td>
839 - <td class="collapsing"><?php esc_html_e( $backup_date ); ?></td>
840 - <td>
841 - <a id="database_backup_button" class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_database_backup item"
842 - website_id="<?php echo intval( $website['id'] ); ?>"
843 - backup_path="<?php echo esc_attr( $backup->absolute_dir ); ?>"
844 - backup_name="<?php echo esc_attr( $backup->file_name ); ?>"
845 - href="javascript:void(0)">
846 - <button class="ui right labeled icon button">
847 - <i class="right undo icon"></i>
848 - <?php esc_html_e( 'Restore', 'mainwp' ); ?>
849 - </button>
850 - </a>
851 - </td>
852 - </tr>
853 - <?php } ?>
854 - </tbody>
855 - <tfoot>
856 - <tr>
857 - <th><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
858 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
859 - <th class="no-sort collapsing"></th>
860 - </tr>
861 - </tfoot>
862 - </table>
863 - </div>
864 - <div class="ui bottom attached tab" data-tab="cpanel-wp-toolkit">
865 - <?php
866 - $available_wptk_backups = array();
867 - /**
868 - * Grab WP-Toolkit status & available backups.
869 - */
870 - $mainwp_enable_wp_toolkit = '0'; // Default to false.
382 + // Check for Plesk and change to WP-Toolkit.
383 + if ( 'Plesk' === $api_provider ) {
384 + $api_provider = 'Plesk (WP Toolkit)';
385 + }
871 386
872 - if ( is_array( $website ) && key_exists( 'id', $website ) ) {
873 - // Grab given website options.
874 - $opts = Api_Backups_Helper::get_website_options(
875 - $website['id'],
876 - array(
877 - 'mainwp_enable_wp_toolkit', // WP-Toolkit status.
878 - 'mainwp_3rd_party_cpanel_wp_toolkit_backups', // WP-Toolkit backups.
879 - )
880 - );
387 + // Grab Last Backup date UTC.
388 + $last_backup_array = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $api_provider_options . '_last_backup' ) );
389 + $last_backup_UTC = isset( $last_backup_array[ 'mainwp_3rd_party_' . $api_provider_options . '_last_backup' ] ) ? $last_backup_array[ 'mainwp_3rd_party_' . $api_provider_options . '_last_backup' ] : '';
881 390
882 - if ( is_array( $opts ) ) {
883 - // Grab WP-Toolkit status.
884 - $mainwp_enable_wp_toolkit = $opts['mainwp_enable_wp_toolkit'] ?? '0';
391 + // If found Convert UTC into chosen WP DateTime formats or return "Awaiting first backup".
392 + if ( '' === $last_backup_UTC ) {
393 + $last_backup = esc_html__( 'Awaiting first backup', 'mainwp' );
394 + } else {
395 + $last_backup = Api_Backups_Utility::format_timestamp( $last_backup_UTC );
396 + }
885 397
886 - // Grab WP-Toolkit backups.
887 - $cpanel_wp_toolkit_backups = ! empty( $opts['mainwp_3rd_party_cpanel_wp_toolkit_backups'] ) ? json_decode( $opts['mainwp_3rd_party_cpanel_wp_toolkit_backups'] ) : false;
888 - $available_wptk_backups = is_object( $cpanel_wp_toolkit_backups ) && ! empty( $cpanel_wp_toolkit_backups->value ) ? $cpanel_wp_toolkit_backups->value : false;
889 - }
890 - }
891 - ?>
892 - <?php if ( $mainwp_enable_wp_toolkit ) : // Display WP-Toolkit Table if enabled. ?>
893 - <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-wptk-table" class="ui mainwp-api-backup-table table" style="width:100%">
894 - <thead>
895 - <tr>
896 - <th colspan="4">
897 - <?php esc_html_e( 'WP Toolkit Backups', 'mainwp' ); ?>
898 - </th>
899 - </tr>
900 - <tr>
901 - <th><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
902 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
903 - <th class="no-sort collapsing"></th>
904 - <th class="no-sort collapsing"></th>
905 - </tr>
906 - </thead>
907 - <tbody>
908 - <?php
909 - if ( ! is_array( $available_wptk_backups ) ) {
910 - $available_wptk_backups = array();
911 - }
912 - foreach ( $available_wptk_backups as $backup ) {
913 - ?>
914 - <?php
915 - $my_unix_timestamp = strtotime( $backup->value->createdAt->value );
916 - $backup_date = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $my_unix_timestamp ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
917 - ?>
918 - <tr>
919 - <td class=""><?php esc_html_e( $backup->value->fileName->value ); ?></td>
920 - <td class=""><?php echo esc_html( $backup_date ); ?></td>
921 - <td></td>
922 - <td class="right aligned">
923 - <button class="ui mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_wptk_backup item"
924 - website_id="<?php echo intval( $website['id'] ); ?>"
925 - backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
926 - data-tooltip="<?php esc_attr_e( 'Restore Backup', 'mainwp' ); ?>"
927 - data-inverted=""
928 - data-position="top center">
929 - <i class="undo icon"></i>
930 - </button>
931 - <?php
932 - /**
933 - * Grab home directory & build download directory.
934 - * Eg.: /home/cpanel_username/wordpress-backups/
935 - */
936 - $home_dir = self::cpanel_action_get_home_directory();
937 - $dirdl = $home_dir . '/wordpress-backups/';
938 - ?>
939 - <button class="ui mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_download_wptk_backup item"
940 - website_id="<?php echo intval( $website['id'] ); ?>"
941 - backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
942 - 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' ) ); ?>"
943 - data-tooltip="<?php esc_attr_e( 'Download Backup', 'mainwp' ); ?>"
944 - data-inverted=""
945 - data-position="top center">
946 - <i class="download icon"></i>
947 - </button>
948 - <button class="ui mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_wptk_backup item"
949 - website_id="<?php echo intval( $website['id'] ); ?>"
950 - backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
951 - data-tooltip="<?php esc_attr_e( 'Delete Backup', 'mainwp' ); ?>"
952 - data-inverted=""
953 - data-position="top center">
954 - <i class="trash icon"></i>
955 - </button>
956 - </td>
957 - </tr>
958 - <?php } ?>
959 - </tbody>
960 - <tfoot>
961 - <tr>
962 - <th><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
963 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
964 - <th class="no-sort collapsing"></th>
965 - <th class="no-sort collapsing"></th>
966 - </tr>
967 - </tfoot>
968 - </table>
969 - <?php else : // Display message if WP-Toolkit is not enabled. ?>
970 - <div class="ui placeholder segment">
971 - <div class="ui icon header">
972 - <i class="key icon"></i>
973 - <?php
974 - printf(
975 - esc_html__(
976 - '%1$sThe WP-Toolkit API has not been enabled.%2$s
977 - Please double check that you have set the cPanel %3$sAPI Key%4$s
978 - on the %5$s page%6$s
979 - and have enabled the %7$sWP Toolkit API%8$s on the %9$s page.',
980 - 'mainwp'
981 - ),
982 - '<em>',
983 - '</em> <br/><br>',
984 - '<em>',
985 - '</em>',
986 - '<a href="admin.php?page=SettingsApiBackups">API Backups Settings</a>',
987 - '</br>',
988 - '<em>',
989 - '</em>',
990 - '<a href="admin.php?page=managesites&id=' . intval( $website_id ) . '">Child Site -> Edit</a>'
991 - );
992 - ?>
993 - </div>
994 - </div>
995 - <?php endif; ?>
996 - </div>
997 - <?php } ?>
998 - <?php // Display GridPane Table. ?>
999 - <?php
1000 - if ( 'gridpane' === $backup_api ) {
1001 - if ( isset( $available_backups->automatic ) ) {
1002 - $available_backups_automatic_list = explode( ',', $available_backups->automatic );
1003 - } else {
1004 - $available_backups_automatic_list = array();
1005 - }
1006 - if ( isset( $available_backups->manual ) ) {
1007 - $available_backups_manual_list = explode( ',', $available_backups->manual );
1008 - } else {
1009 - $available_backups_manual_list = array();
1010 - }
1011 - ?>
1012 - <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
1013 - <thead>
1014 - <tr>
1015 - <th><?php esc_html_e( 'GridPane Backup Name', 'mainwp' ); ?></th>
1016 - <th><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
1017 - <th class="no-sort collapsing"></th>
1018 - <th class="no-sort collapsing"></th>
1019 - </tr>
1020 - </thead>
1021 - <tbody>
1022 - <?php foreach ( $available_backups_automatic_list as $backup ) { ?>
1023 - <tr>
1024 - <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php esc_html_e( $backup ); ?></td>
1025 - <td><?php esc_html_e( 'Automatic', 'mainwp' ); ?></td>
1026 - <td></td>
1027 - <td class="collapsing right aligned">
1028 - <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1029 - website_id="<?php echo intval( $website['id'] ); ?>"
1030 - backup_type="<?php echo esc_attr( 'automatic' ); ?>"
1031 - backup_name="<?php echo esc_attr( $backup ); ?>"
1032 - href="javascript:void(0)">
1033 - <i class="undo icon"></i>
1034 - </a>
1035 - <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button"
1036 - website_id="<?php echo intval( $website['id'] ); ?>"
1037 - backup_type="<?php echo esc_attr( 'automatic' ); ?>"
1038 - backup_name="<?php echo esc_attr( $backup ); ?>"
1039 - href="javascript:void(0)">
1040 - <i class="trash icon"></i>
1041 - </a>
1042 - </td>
1043 - </tr>
1044 - <?php } ?>
1045 - <?php foreach ( $available_backups_manual_list as $backup ) { ?>
1046 - <tr>
1047 - <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php esc_html_e( $backup ); ?></td>
1048 - <td><?php esc_html_e( 'Manual', 'mainwp' ); ?></td>
1049 - <td></td>
1050 - <td class="collapsing right aligned">
1051 - <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1052 - website_id="<?php echo intval( $website['id'] ); ?>"
1053 - backup_type="<?php echo esc_attr( 'manual' ); ?>"
1054 - backup_name="<?php echo esc_attr( $backup ); ?>"
1055 - href="javascript:void(0)">
1056 - <i class="undo icon"></i>
1057 - </a>
1058 - <a class="mainwp_3rd_party_api_<?php esc_attr_e( $backup_api ); ?>_action_delete_backup ui mini icon button"
1059 - website_id="<?php echo intval( $website['id'] ); ?>"
1060 - backup_type="<?php echo esc_attr( 'manual' ); ?>"
1061 - backup_name="<?php echo esc_attr( $backup ); ?>"
1062 - href="javascript:void(0)">
1063 - <i class="trash icon"></i>
1064 - </a>
1065 - </td>
1066 - </tr>
1067 - <?php } ?>
1068 - </tbody>
1069 - <tfoot>
1070 - <tr>
1071 - <th><?php esc_html_e( 'GridPane Backup Name', 'mainwp' ); ?></th>
1072 - <th><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
1073 - <th class="no-sort collapsing"></th>
1074 - <th class="no-sort collapsing"></th>
1075 - </tr>
1076 - </tfoot>
1077 - </table>
1078 - <?php } ?>
1079 - <?php // Display Cloudways Table. ?>
1080 - <?php
1081 - if ( 'cloudways' === $backup_api ) {
398 + ?>
399 + <tr website-id="<?php echo intval( $website->id ); ?>" provider-name="<?php echo esc_attr( $api_provider ); ?>">
400 + <td class="check-column">
401 + <?php if ( 'None' !== $api_provider ) : ?>
402 + <span class="ui checkbox">
403 + <label for="table-checkbox"></label>
404 + <input id="table-checkbox" type="checkbox" value="<?php echo intval( $website->id ); ?>" status="queue" >
405 + </span>
406 + <?php else : ?>
407 + <span class="ui disabled checkbox">
408 + <label for="table-checkbox"></label>
409 + </span>
410 + <?php endif; ?>
411 + </td>
412 + <td>
413 + <div>
414 + <a href="<?php MainWP_Site_Open::get_open_site_admin_link( $website->id, true ); //phpcs:ignore -- ok. ?>" target="_blank">
415 + <i class="sign in alternate icon"></i>
416 + </a>
417 + <a href="admin.php?page=ManageSitesApiBackups&id=<?php echo intval( $website->id ); ?>"><?php echo esc_html( $website->name ); ?></a> <span class="running"></span>
418 + </div>
419 + <span class="ui small text">
420 + <a href="<?php echo esc_url( $website->url ); ?>" target="_blank" class="ui grey text"><?php echo esc_url( $website->url ); ?></a>
421 + </span>
422 + </td>
423 + <td><?php echo esc_html( $api_provider ); ?></td>
424 + <td class="last-backup-date" ><?php echo ( $last_backup ) ? esc_html( $last_backup ) : esc_html__( 'Awaiting first backup', 'mainwp' ); ?></td>
425 + <td class="collapsing not-selectable">
426 + <i class="ui notched circle loading icon" style="display:none;"></i>
427 + <div class="ui right pointing dropdown" style="z-index: 999">
428 + <a href="javascript:void(0)"><i class="ellipsis vertical icon"></i></a>
429 + <div class="menu">
430 + <?php if ( 'cPanel' === $api_provider ) : ?>
431 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $api_provider_options ); ?>_action_full_backup item"
432 + website_id="<?php echo intval( $website->id ); ?>" href="javascript:void(0)">
433 + <?php esc_html_e( 'Backup', 'mainwp' ); ?>
434 + </a>
435 + <?php elseif ( 'None' !== $api_provider && 'cPanel' !== $api_provider ) : ?>
436 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $api_provider_options ); ?>_action_backup item"
437 + website_id="<?php echo intval( $website->id ); ?>" href="javascript:void(0)">
438 + <?php esc_html_e( 'Backup', 'mainwp' ); ?>
439 + </a>
440 + <?php endif; ?>
441 + <a class="item" href="admin.php?page=ManageSitesApiBackups&id=<?php echo intval( $website->id ); ?>"><?php esc_html_e( 'Manage Backups', 'mainwp' ); ?></a>
442 + </div>
443 + </div>
444 + </td>
445 + </tr>
446 + <?php
447 + }
448 + Api_Backups_Helper::free_result( $websites );
449 + ?>
450 + </tbody>
451 + </table>
452 + <script type="text/javascript">
453 + let responsive = true;
454 + if ( jQuery( window ).width() > 1140 ) {
455 + responsive = false;
456 + }
457 + jQuery( document ).ready( function() {
458 + jQuery( '.mainwp-api-backup-table' ).DataTable( {
459 + "stateSave": true,
460 + "stateDuration": 0,
461 + "colReorder" : {columns:":not(.check-column):not(:last-child)"},
462 + "responsive": responsive,
463 + "scrollX": true,
464 + "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
465 + "columnDefs": [ { "targets": 'no-sort', "orderable": false } ],
466 + "order": [ [ 1, "asc" ] ],
467 + "language": { "emptyTable": "No backups found." },
468 + "drawCallback": function( settings ) {
469 + setTimeout(() => {
470 + jQuery('#mainwp-3rd-party-backups-table .ui.checkbox').checkbox();
471 + jQuery('.mainwp-api-backup-table .ui.dropdown').dropdown();
472 + mainwp_datatable_fix_menu_overflow('#mainwp-3rd-party-backups-table');
473 + }, 1000);
474 + },
475 + select: {
476 + items: 'row',
477 + style: 'multi+shift',
478 + selector: 'tr>td:not(.not-selectable)'
479 + }
480 + }).on('select', function (e, dt, type, indexes) {
481 + if( 'row' == type ){
482 + dt.rows(indexes)
483 + .nodes()
484 + .to$().find('td.check-column .ui.checkbox' ).checkbox('set checked');
485 + }
486 + }).on('deselect', function (e, dt, type, indexes) {
487 + if( 'row' == type ){
488 + dt.rows(indexes)
489 + .nodes()
490 + .to$().find('td.check-column .ui.checkbox' ).checkbox('set unchecked');
491 + }
492 + }).on( 'columns-reordered', function () {
493 + setTimeout(() => {
494 + jQuery( '#mainwp-3rd-party-backups-table .ui.dropdown' ).dropdown();
495 + jQuery( '#mainwp-3rd-party-backups-table .ui.checkbox' ).checkbox();
496 + mainwp_datatable_fix_menu_overflow('#mainwp-3rd-party-backups-table');
497 + mainwp_table_check_columns_init(); // ajax: to fix checkbox all.
498 + }, 1000);
499 + });
500 + } );
501 + </script>
502 + <?php
503 + }
1082 504
1083 - // Check if backups are available.
1084 - if ( isset( $available_backups->application_backup_exists ) && true === $available_backups->application_backup_exists ) {
1085 - $available_backups = $available_backups->backup_dates;
1086 - } else {
1087 - $available_backups = array();
1088 - }
505 + /**
506 + * Render the Individual 3rd Party API Backup Page.
507 + *
508 + * @param mixed $website The Child Site Object.
509 + */
510 + public function render_api_backups_site( $website ) { //phpcs:ignore -- NOSONAR - complex function.
1089 511
1090 - ?>
1091 - <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
1092 - <thead>
1093 - <tr>
1094 - <th><?php esc_html_e( 'Cloudways Backup Type', 'mainwp' ); ?></th>
1095 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1096 - <th class="no-sort collapsing"></th>
1097 - <th class="no-sort collapsing"></th>
1098 - </tr>
1099 - </thead>
1100 - <tbody>
1101 - <?php foreach ( $available_backups as $backup ) { ?>
1102 - <tr>
1103 - <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php esc_html_e( 'Application Backup', 'mainwp' ); ?></td>
1104 - <td><?php echo esc_html( gmdate( 'm-d-Y ( h:i:s )', strtotime( $backup ) ) ); ?></td>
1105 - <td></td>
1106 - <td>
1107 - <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>
1108 - </td>
1109 - </tr>
1110 - <?php } ?>
1111 - </tbody>
1112 - <tfoot>
1113 - <tr>
1114 - <th><?php esc_html_e( 'Cloudways Backup Type', 'mainwp' ); ?></th>
1115 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1116 - <th class="no-sort collapsing"></th>
1117 - <th class="no-sort collapsing"></th>
1118 - </tr>
1119 - </tfoot>
1120 - </table>
1121 - <?php } ?>
1122 - <?php // Display Vultr Table. ?>
1123 - <?php
1124 - if ( 'vultr' === $backup_api ) {
1125 - if ( isset( $available_backups->snapshots ) ) {
1126 - $available_snapshots_list = $available_backups->snapshots;
1127 - } else {
1128 - $available_snapshots_list = array();
1129 - }
1130 - if ( isset( $available_backups->backups ) ) {
1131 - $available_backups_list = $available_backups->backups;
1132 - } else {
1133 - $available_backups_list = array();
1134 - }
1135 - ?>
1136 - <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
1137 - <thead>
1138 - <tr>
1139 - <th><?php esc_html_e( 'Vultr Backup Label', 'mainwp' ); ?></th>
1140 - <th><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1141 - <th><?php esc_html_e( 'Compressed Size', 'mainwp' ); ?></th>
1142 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1143 - <th><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1144 - <th class="no-sort collapsing"></th>
1145 - <th class="no-sort collapsing"></th>
1146 - </tr>
1147 - </thead>
1148 - <tbody>
1149 - <?php
1150 - foreach ( $available_snapshots_list as $backup ) {
1151 - if ( empty( $backup ) || ! is_object( $backup ) || empty( $backup->date_created ) ) {
1152 - continue;
1153 - }
1154 - ?>
1155 - <tr>
1156 - <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->description ); ?></td>
1157 - <td><?php echo esc_html( Api_Backups_Utility::human_filesize( $backup->size ) ); ?></td>
1158 - <td><?php echo esc_html( Api_Backups_Utility::human_filesize( $backup->compressed_size ) ); ?></td>
1159 - <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->date_created ) ) ); ?></td>
1160 - <td><?php echo esc_html( $backup->status ); ?></td>
1161 - <td></td>
1162 - <td class="collapsing right aligned">
1163 - <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>
1164 - <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>
1165 - </td>
1166 - </tr>
1167 - <?php } ?>
1168 - <?php
1169 - foreach ( $available_backups_list as $backup ) {
1170 - if ( empty( $backup ) || ! is_object( $backup ) || empty( $backup->date_created ) ) {
1171 - continue;
1172 - }
1173 - ?>
1174 - <tr>
1175 - <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->description ); ?></td>
1176 - <td><?php echo esc_html( Api_Backups_Utility::human_filesize( $backup->size ) ); ?></td>
1177 - <td><?php esc_html_e( 'N/A', 'mainwp' ); ?></td>
1178 - <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->date_created ) ) ); ?></td>
1179 - <td><?php echo esc_html( $backup->status ); ?></td>
1180 - <td></td>
1181 - <td class="collapsing right aligned">
1182 - <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1183 - website_id="<?php echo intval( $website['id'] ); ?>"
1184 - snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1185 - href="javascript:void(0)">
1186 - <i class="undo icon"></i>
1187 - </a>
1188 - <a class="mainwp_3rd_party_api_<?php esc_attr_e( $backup_api ); ?>_action_delete_backup ui mini icon button"
1189 - website_id="<?php echo intval( $website['id'] ); ?>"
1190 - snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1191 - href="javascript:void(0)">
1192 - <i class="trash icon"></i>
1193 - </a>
1194 - </td>
1195 - </tr>
1196 - <?php } ?>
1197 - </tbody>
1198 - <tfoot>
1199 - <tr>
1200 - <th><?php esc_html_e( 'Vultr Backup Label', 'mainwp' ); ?></th>
1201 - <th><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1202 - <th><?php esc_html_e( 'Compressed Size', 'mainwp' ); ?></th>
1203 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1204 - <th><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1205 - <th class="no-sort collapsing"></th>
1206 - <th class="no-sort collapsing"></th>
1207 - </tr>
1208 - </tfoot>
1209 - </table>
1210 - <?php } ?>
1211 - <?php // Display Linode Table. ?>
1212 - <?php
1213 - if ( 'linode' === $backup_api ) {
512 + $available_backups = array();
1214 513
1215 - // Automatic Backups.
1216 - if ( isset( $available_backups->automatic ) ) {
1217 - $available_backups_automatic_list = $available_backups->automatic;
1218 - } else {
1219 - $available_backups_automatic_list = array();
1220 - }
514 + if ( empty( $website ) ) {
515 + return;
516 + }
1221 517
1222 - // Manual Backups.
1223 - if ( isset( $available_backups->snapshot ) ) {
1224 - $available_backups_snapshot_list = $available_backups->snapshot;
1225 - } else {
1226 - $available_backups_snapshot_list = array();
1227 - }
1228 - ?>
1229 - <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
1230 - <thead>
1231 - <tr>
1232 - <th><?php esc_html_e( 'Akamai (Linode) Backup Type', 'mainwp' ); ?></th>
1233 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1234 - <th><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1235 - <th class="no-sort collapsing"></th>
1236 - <th class="no-sort collapsing"></th>
1237 - <th class="no-sort collapsing"></th>
1238 - </tr>
1239 - </thead>
1240 - <tbody>
1241 - <?php foreach ( $available_backups_automatic_list as $backup ) { ?>
1242 - <tr>
1243 - <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php esc_html_e( $backup->type ); ?></td>
1244 - <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->created ) ) ); ?></td>
1245 - <td class="operation_status"><?php echo esc_html( $backup->status ); ?></td>
1246 - <td></td>
1247 - <td></td>
1248 - <td>
1249 - <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1250 - website_id="<?php echo intval( $website['id'] ); ?>"
1251 - backup_type="<?php echo esc_attr( $backup->type ); ?>"
1252 - backup_id="<?php echo esc_attr( $backup->id ); ?>"
1253 - href="javascript:void(0)">
1254 - <i class="undo icon"></i>
1255 - </a>
1256 - </td>
1257 - </tr>
1258 - <?php } ?>
1259 - <?php foreach ( $available_backups_snapshot_list as $backup ) { ?>
1260 - <?php if ( null !== $backup ) { ?>
1261 - <tr>
1262 - <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php esc_html_e( $backup->type ); ?></td>
1263 - <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->created ) ) ); ?></td>
1264 - <td><?php echo esc_html( $backup->status ); ?></td>
1265 - <td></td>
1266 - <td></td>
1267 - <td>
518 + $website_id = $website['id'];
1268 519
1269 - <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1270 - website_id="<?php echo intval( $website['id'] ); ?>"
1271 - backup_type="<?php echo esc_attr( $backup->type ); ?>"
1272 - backup_id="<?php echo esc_attr( $backup->id ); ?>"
1273 - href="javascript:void(0)">
1274 - <i class="undo icon"></i>
1275 - </a>
1276 - </td>
1277 - </tr>
1278 - <?php } ?>
1279 - <?php } ?>
1280 - </tbody>
1281 - <tfoot>
1282 - <tr>
1283 - <th><?php esc_html_e( 'Akamai (Linode) Backup Type', 'mainwp' ); ?></th>
1284 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1285 - <th><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1286 - <th class="no-sort collapsing"></th>
1287 - <th class="no-sort collapsing"></th>
1288 - <th class="no-sort collapsing"></th>
1289 - </tr>
1290 - </tfoot>
1291 - </table>
1292 - <?php } ?>
1293 - <?php // Display DigitalOcean Table. ?>
1294 - <?php
1295 - if ( 'digitalocean' === $backup_api ) {
1296 - if ( isset( $available_backups->snapshots ) ) {
1297 - $available_backups = $available_backups->snapshots;
1298 - }
1299 - if ( ! is_array( $available_backups ) ) {
1300 - $available_backups = array();
1301 - }
1302 - ?>
1303 - <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
1304 - <thead>
1305 - <tr>
1306 - <th><?php esc_html_e( 'DigitalOcean Backup Label', 'mainwp' ); ?></th>
1307 - <th><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1308 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1309 - <th class="no-sort collapsing"></th>
1310 - <th class="no-sort collapsing"></th>
1311 - </tr>
1312 - </thead>
1313 - <tbody>
1314 - <?php foreach ( $available_backups as $backup ) { ?>
1315 - <tr>
1316 - <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php esc_html_e( $backup->name ); ?></td>
1317 - <td><?php echo intval( $backup->size_gigabytes ); ?>GB</td>
1318 - <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->created_at ) ) ); ?></td>
1319 - <td></td>
1320 - <td class="collapsing right aligned">
1321 - <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1322 - website_id="<?php echo intval( $website['id'] ); ?>"
1323 - snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1324 - href="javascript:void(0)">
1325 - <i class="undo icon"></i>
1326 - </a>
1327 - <a class="mainwp_3rd_party_api_<?php esc_attr_e( $backup_api ); ?>_action_delete_backup ui mini icon button"
1328 - website_id="<?php echo intval( $website['id'] ); ?>"
1329 - snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1330 - href="javascript:void(0)">
1331 - <i class="trash icon"></i>
1332 - </a>
1333 - </td>
1334 - </tr>
1335 - <?php } ?>
1336 - </tbody>
1337 - <tfoot>
1338 - <tr>
1339 - <th><?php esc_html_e( 'DigitalOcean Backup Label', 'mainwp' ); ?></th>
1340 - <th><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1341 - <th><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1342 - <th class="no-sort collapsing"></th>
1343 - <th class="no-sort collapsing"></th>
1344 - </tr>
1345 - </tfoot>
1346 - </table>
1347 - <?php } ?>
520 + /**
521 + * Grab Child Site data needed to display Table.
522 + */
1348 523
1349 - </div>
1350 - <script type="text/javascript">
1351 - let responsive = true;
1352 - if ( jQuery( window ).width() > 1140 ) {
1353 - responsive = false;
1354 - }
1355 - jQuery( document ).ready( function() {
524 + // Grab backup api name.
525 + $site_api_name = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_api' ) );
526 + $backup_api = isset( $site_api_name['mainwp_3rd_party_api'] ) ? strtolower( $site_api_name['mainwp_3rd_party_api'] ) : null;
1356 527
1357 - jQuery( '.mainwp-api-backup-table' ).DataTable( {
1358 - "stateSave": true,
1359 - "stateDuration": 0,
1360 - "colReorder" : {
1361 - fixedColumnsLeft: 1,
1362 - fixedColumnsRight: 1
1363 - },
1364 - "responsive": responsive,
1365 - "scrollX": false,
1366 - "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
1367 - "columnDefs": [ { "targets": 'no-sort', "orderable": false } ],
1368 - "order": [ [ 1, "asc" ] ],
1369 - "language": { "emptyTable": "No backups found." },
1370 - "drawCallback": function( settings ) {
1371 - jQuery('.mainwp-api-backup-table .ui.checkbox').checkbox();
1372 - jQuery('.mainwp-api-backup-table .ui.dropdown').dropdown();
1373 - mainwp_datatable_fix_menu_overflow('.mainwp-api-backup-table', -55, 10 );
1374 - },
1375 - } );
1376 - } );
1377 - </script>
1378 - <?php
1379 - } // END if.
1380 - }
528 + // Grab Child Sites available backups from DB to display in table.
529 + $site_available_backups = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $backup_api . '_available_backups' ) );
1381 530
1382 - /*********************************************************************************
1383 - * Cloudways API Methods.
1384 - **********************************************************************************/
531 + // Check if valid JSON or not. If not, then it's a string - do not decode it.
532 + if ( isset( $site_available_backups[ 'mainwp_3rd_party_' . $backup_api . '_available_backups' ] ) && ! empty( $site_available_backups[ 'mainwp_3rd_party_' . $backup_api . '_available_backups' ] ) ) {
533 + json_decode( $site_available_backups[ 'mainwp_3rd_party_' . $backup_api . '_available_backups' ] );
534 + if ( json_last_error() === JSON_ERROR_NONE ) {
535 + // JSON is valid.
536 + $available_backups = json_decode( $site_available_backups[ 'mainwp_3rd_party_' . $backup_api . '_available_backups' ] );
537 + } else {
538 + // JSON is invalid treat it as a string.
539 + $available_backups = $site_available_backups[ 'mainwp_3rd_party_' . $backup_api . '_available_backups' ];
540 + }
541 + } else {
542 + $available_backups = array();
543 + }
1385 544
1386 - /**
1387 - * Call Cloudways API, Authenticate & perform given method.
1388 - *
1389 - * Use this function to contact CW API
1390 - * We use OAuth, an open standard for authorization. Here are the steps involved:
1391 - * 1. Get your API Key from here: https://platform.cloudways.com/api
1392 - * 2. Enter in your account email address and API Key below.
1393 - *
1394 - * @param string $method GET|POST|PUT|DELETE.
1395 - * @param string $url relative URL for the call.
1396 - * @param string $accessToken Access token generated using OAuth Call.
1397 - * @param array $post Optional post data for the call.
1398 - * @return object Output from CW API.
1399 - */
1400 - public static function call_cloudways_api( $method, $url, $accessToken, $post = array() ) {
1401 - $baseURL = 'https://api.cloudways.com/api/v1';
545 + if ( empty( $backup_api ) ) {
546 + $title = esc_html__( 'No API Backup Solution has been chosen.', 'mainwp' );
547 + /* translators: %1$s: Link to API Backups Settings page, %2$s: Link to Child Site Settings page */
548 + $msg_format = __( 'Please double check that you have set the API Key on the %1$s page and have set the Instance ID on the %2$s page.', 'mainwp' );
549 + $message = sprintf(
550 + $msg_format,
551 + '<a href="' . esc_url( admin_url( 'admin.php?page=SettingsApiBackups' ) ) . '">' . esc_html__( 'API Backups Settings', 'mainwp' ) . '</a>',
552 + '<a href="' . esc_url( admin_url( 'admin.php?page=managesites&id=' . intval( $website_id ) ) ) . '">' . esc_html__( 'Child Site &rarr; Settings page', 'mainwp' ) . '</a>'
553 + );
554 + $icon = '<em data-emoji=":closed_lock_with_key:" class="big"></em>';
555 + \MainWP\Dashboard\MainWP_UI::render_empty_page_placeholder( $title, $message, $icon );
556 + } else {
557 + $columns = 'one';
558 + if ( 'cpanel' === $backup_api || 'plesk' === $backup_api ) {
559 + $columns = 'two';
560 + }
561 + ?>
562 + <div class="mainwp-actions-bar">
563 + <div class="ui grid">
564 + <div class="ui <?php echo esc_html( $columns ); ?> column row">
565 + <div class="middle aligned column ui">
566 + <?php if ( 'cpanel' === $backup_api ) : ?>
567 + <div id="mainwp_api_cpanel_backup_tabs" class="ui top attached tabular menu">
568 + <div class="active item" data-tab="cpanel-native"><i class="fitted cpanel big icon"></i></div>
569 + <div class="item" data-tab="cpanel-wp-toolkit"><i class="fitted wordpress big icon"></i></div><?php //phpcs:ignore -- skip wordpress.?>
570 + </div>
571 + <?php endif; ?>
572 + </div>
573 + <div class="right aligned middle aligned column">
574 + <?php if ( 'cpanel' === $backup_api ) : ?>
575 + <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_create_full_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini green button"><?php esc_html_e( 'Backup Files &amp; Database', 'mainwp' ); ?></button>
576 + <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_create_wptk_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini green button hidden"><?php esc_html_e( 'Backup Now', 'mainwp' ); ?></button>
577 + <?php else : ?>
578 + <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_individual_create_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini green button"><?php esc_html_e( 'Backup Now', 'mainwp' ); ?></button>
579 + <?php endif; ?>
580 + <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_refresh_available_backups" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini green button"><?php esc_html_e( 'Refresh Available Backups', 'mainwp' ); ?></button>
1402 581
1403 - $ch = curl_init();
1404 - curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, $method );
1405 - curl_setopt( $ch, CURLOPT_URL, $baseURL . $url );
1406 - curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
582 + <?php // Render DigitalOcean specific action buttons. ?>
583 + <?php
584 + if ( 'digitalocean' === $backup_api ) {
585 + // Grab Linode instance id.
586 + $digitalocean_droplet_id = Api_Backups_Helper::get_website_options(
587 + $website,
588 + array(
589 + 'mainwp_3rd_party_instance_id',
590 + )
591 + );
592 + $droplet_id = isset( $digitalocean_droplet_id['mainwp_3rd_party_instance_id'] ) ? $digitalocean_droplet_id['mainwp_3rd_party_instance_id'] : null;
593 + ?>
594 + <a href="https://cloud.digitalocean.com/droplets/<?php echo esc_attr( $droplet_id ); ?>/snapshots" target="_blank" class="ui mini button">
595 + <i class="external icon"></i>
596 + <?php esc_html_e( 'View on DigitalOcean', 'mainwp' ); ?>
597 + </a>
598 + <?php } ?>
599 + <?php // Render Linode specific action buttons. ?>
600 + <?php
601 + if ( 'linode' === $backup_api ) {
602 + // Grab Linode instance id.
603 + $linode_instance_id = Api_Backups_Helper::get_website_options(
604 + $website,
605 + array(
606 + 'mainwp_3rd_party_instance_id',
607 + )
608 + );
609 + $instance_id = isset( $linode_instance_id['mainwp_3rd_party_instance_id'] ) ? $linode_instance_id['mainwp_3rd_party_instance_id'] : null;
610 + ?>
611 + <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_cancel_backups" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini button"><?php esc_html_e( 'Disable & Remove Backups on This Linode', 'mainwp' ); ?></button>
612 + <a href="https://cloud.linode.com/linodes/<?php echo esc_attr( $instance_id ); ?>/backup" target="_blank" class="ui mini button">
613 + <i class="external icon"></i>
614 + <?php esc_html_e( 'View on Akamai (Linode)', 'mainwp' ); ?>
615 + </a>
616 + <?php } ?>
617 + <?php // Render Cloudways specific action buttons. ?>
618 + <?php
619 + if ( 'cloudways' === $backup_api ) {
620 + // Grab Cloudways app id.
621 + $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_app_id' ) );
622 + $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
623 + ?>
624 + <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini button"><?php esc_html_e( 'Delete 24hr Restore Point', 'mainwp' ); ?></button>
625 + <a href="https://platform.cloudways.com/apps/<?php echo esc_attr( $app_id ); ?>/restore" target="_blank" class="ui mini button">
626 + <i class="external icon"></i>
627 + <?php esc_html_e( 'View on Cloudways', 'mainwp' ); ?>
628 + </a>
629 + <?php } ?>
630 + <?php // Render Vultr specific action buttons. ?>
631 + <?php
632 + if ( 'vultr' === $backup_api ) {
633 + // Grab Vultr Instance id.
634 + $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_instance_id' ) );
635 + $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
636 + ?>
637 + <a href="https://my.vultr.com/subs/?id=<?php echo esc_attr( $instance_id ); ?>#subssnapshots" target="_blank" class="ui mini button">
638 + <i class="external icon"></i>
639 + <?php esc_html_e( 'View on Vultr', 'mainwp' ); ?>
640 + </a>
641 + <?php } ?>
642 + <?php // Render GridPane specific action buttons. ?>
643 + <?php if ( 'gridpane' === $backup_api ) { ?>
644 + <a href="https://my.gridpane.com/sites" target="_blank" class="ui mini button">
645 + <i class="external icon"></i>
646 + <?php esc_html_e( 'View on GridPane', 'mainwp' ); ?>
647 + </a>
648 + <?php } ?>
649 + </div>
650 + </div>
651 + </div>
652 + </div>
653 + <div class="ui padded segment">
1407 654
1408 - // Set Authorization Header.
1409 - if ( $accessToken ) {
1410 - curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Authorization: Bearer ' . $accessToken ) );
1411 - }
655 + <?php // Render action notifications. I get replaced by JS. ?>
656 + <div id="mainwp-api-backups-message-zone" class="ui message" style="display: none;">
657 + <i class="icon close"></i>
658 + <div class="content">
659 + <div class="message"></div>
660 + </div>
661 + </div>
1412 662
1413 - // Set Post Parameters.
1414 - $encoded = '';
1415 - if ( count( $post ) ) {
1416 - foreach ( $post as $name => $value ) {
1417 - $encoded .= rawurlencode( $name ) . '=' . rawurlencode( $value ) . '&';
1418 - }
1419 - $encoded = substr( $encoded, 0, strlen( $encoded ) - 1 );
663 + <?php // Render info notifications. ?>
664 + <?php // Render Linode info notifications. ?>
665 + <?php if ( 'linode' === $backup_api ) { ?>
666 + <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message1' ) ) : ?>
667 + <div class="ui info message">
668 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message1"></i>
669 + <div><?php esc_html_e( 'Three backup slots are executed and rotated automatically: a daily backup, a 2-7 day old backup, and an 8-14 day old backup. You will need to enable backups on your Akamai (Linode) Instance in order to use this feature.', 'mainwp' ); ?></div>
670 + </div>
671 + <div class="ui info message">
672 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message1"></i>
673 + <div><?php esc_html_e( 'Please note that when you click the Disable & Remove Backups button it cancels the Backup service on the given Linode. Deletes all of this Linode\'s existing backups forever.', 'mainwp' ); ?></div>
674 + </div>
675 + <?php endif; ?>
676 + <?php } ?>
677 + <?php if ( 'cloudways' === $backup_api ) { ?>
678 + <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message2' ) ) : ?>
679 + <div class="ui info message">
680 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message2"></i>
681 + <div><?php esc_html_e( ' This page allows you to back up and restore your currently available Cloudways backups.', 'mainwp' ); ?></div>
682 + </div>
683 + <div class="ui info message">
684 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message2"></i>
685 + <p><?php esc_html_e( 'Please note that Cloudways does not allow you to delete individual backups.', 'mainwp' ); ?></p>
686 + <p><?php esc_html_e( 'A local copy of your application will be saved automatically before you restore your application using the restore feature.', 'mainwp' ); ?></p>
687 + <p><?php esc_html_e( 'To use the restore feature again, you will have to either delete this local copy by clicking the Delete 24hr Restore Point button or roll your application back to the state it was before you restored it via the Cloudways Account UI.', 'mainwp' ); ?></p>
688 + <p><?php esc_html_e( 'This local copy is kept for the first 24 hours, after which it is automatically removed.', 'mainwp' ); ?></p>
689 + </div>
690 + <?php endif; ?>
691 + <?php } ?>
692 + <?php if ( 'digitalocean' === $backup_api ) { ?>
693 + <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message3' ) ) : ?>
694 + <div class="ui info message">
695 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message3"></i>
696 + <div><?php esc_html_e( ' This page allows you to back up and restore your currently available DigitalOcean backups.', 'mainwp' ); ?></div>
697 + </div>
698 + <?php endif; ?>
699 + <?php } ?>
700 + <?php if ( 'gridpane' === $backup_api ) { ?>
701 + <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message4' ) ) : ?>
702 + <div class="ui info message">
703 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message4"></i>
704 + <div><?php esc_html_e( ' This page allows you to back up and restore your currently available GridPane backups.', 'mainwp' ); ?></div>
705 + </div>
706 + <?php endif; ?>
707 + <?php } ?>
708 + <?php if ( 'vultr' === $backup_api ) { ?>
709 + <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message5' ) ) : ?>
710 + <div class="ui info message">
711 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message5"></i>
712 + <div><?php esc_html_e( ' This page allows you to back up and restore your currently available Vultr backups.', 'mainwp' ); ?></div>
713 + </div>
714 + <?php endif; ?>
715 + <?php } ?>
716 + <?php // Display Kinsta Table. ?>
717 + <?php
718 + if ( 'kinsta' === $backup_api ) {
1420 719
1421 - curl_setopt( $ch, CURLOPT_POSTFIELDS, $encoded );
1422 - curl_setopt( $ch, CURLOPT_POST, 1 );
1423 - }
720 + if ( is_object( $available_backups ) ) {
721 + $available_backups = $available_backups->environment->backups;
722 + } else {
723 + $available_backups = array();
724 + }
1424 725
1425 - $output = curl_exec( $ch );
726 + ?>
727 + <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-message' ) ) : ?>
728 + <div class="ui info message">
729 + <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-message"></i>
730 + <div><?php esc_html_e( 'You can create up to 5 manual backups. Each manual backup will be stored for 14 days.', 'mainwp' ); ?></div>
731 + </div>
732 + <?php
733 + endif;
734 + $el_id_wp_1 = $website['id'];
735 + ?>
736 + <table id="mainwp-siteid-<?php echo intval( $el_id_wp_1 ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
737 + <thead>
738 + <tr>
739 + <th scope="col"><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
740 + <th scope="col"><?php esc_html_e( 'Note', 'mainwp' ); ?></th>
741 + <th scope="col"><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
742 + <th scope="col"><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
743 + <th scope="col" class="no-sort collapsing"></th>
744 + <th scope="col" class="no-sort collapsing"></th>
745 + </tr>
746 + </thead>
747 + <tbody>
748 + <?php foreach ( $available_backups as $backup ) { ?>
749 + <?php
750 + // Convert Kinsta backup date to human readable format.
751 + $backup_date = Api_Backups_Utility::format_timestamp( intval( $backup->created_at / 1000 ) );
752 + ?>
753 + <tr>
754 + <td class="collapsing"><?php echo esc_html( $backup->name ); ?></td>
755 + <td class="collapsing"><?php echo esc_html( $backup->note ); ?></td>
756 + <td class="collapsing"><?php echo esc_html( $backup->type ); ?></td>
757 + <td class="collapsing"><?php echo esc_html( $backup_date ); ?></td>
758 + <td></td>
759 + <td class="collapsing right aligned">
760 + <button id="kinsta_restore_button" class="ui circular icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup item"
761 + website_id="<?php echo intval( $website['id'] ); ?>"
762 + backup_id="<?php echo intval( $backup->id ); ?>"
763 + data-tooltip="<?php esc_attr_e( 'Restore Backup', 'mainwp' ); ?>"
764 + data-inverted=""
765 + data-position="top center">
766 + <i class="undo icon"></i>
767 + </button>
768 + <button id="kinsta_delete_button" class="ui circular icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup item"
769 + website_id="<?php echo intval( $website['id'] ); ?>"
770 + backup_id="<?php echo intval( $backup->id ); ?>"
771 + data-tooltip="<?php esc_attr_e( 'Delete Backup', 'mainwp' ); ?>"
772 + data-inverted=""
773 + data-position="top center">
774 + <i class="trash icon"></i>
775 + </button>
776 + </td>
777 + </tr>
778 + <?php } ?>
779 + </tbody>
780 + <tfoot>
781 + <tr>
782 + <th scope="col"><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
783 + <th scope="col"><?php esc_html_e( 'Environment', 'mainwp' ); ?></th>
784 + <th scope="col"><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
785 + <th scope="col"><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
786 + <th scope="col" class="no-sort collapsing"></th>
787 + <th scope="col" class="no-sort collapsing"></th>
788 + </tr>
789 + </tfoot>
790 + </table>
791 + <div class="ui divider hidden"></div>
792 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
793 + <thead>
794 + <tr>
795 + <th scope="col" colspan="3">
796 + <div class="ui equal width grid">
797 + <div class="left aligned middle aligned column">
798 + <?php esc_html_e( 'Downloadable Backups', 'mainwp' ); ?>
799 + </div>
800 + </div>
801 + </th>
802 + </tr>
803 + <tr>
804 + <th scope="col"><?php esc_html_e( 'Created', 'mainwp' ); ?></th>
805 + <th scope="col"><?php esc_html_e( 'Expiry', 'mainwp' ); ?></th>
806 + <th scope="col" class="no-sort collapsing"></th>
807 + </tr>
808 + </thead>
809 + <tbody>
810 + <?php
811 + // Grab Downloadable Backups.
812 + $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_kinsta_downloadable_backups' ) );
813 + $downloadable_backups = isset( $site_options['mainwp_3rd_party_kinsta_downloadable_backups'] ) ? $site_options['mainwp_3rd_party_kinsta_downloadable_backups'] : '';
814 + $downloadable_backups = json_decode( $downloadable_backups );
815 + ?>
816 + <?php if ( is_object( $downloadable_backups ) ) { ?>
817 + <?php foreach ( $downloadable_backups->environment->downloadable_backups as $backup ) { ?>
818 + <?php
1426 819
1427 - $httpcode = (string) curl_getinfo( $ch, CURLINFO_HTTP_CODE );
820 + // Convert Kinsta backup dates to human readable format.
821 + $created_date = Api_Backups_Utility::format_timestamp( intval( $backup->created_at / 1000 ) );
822 + $expiry_date = Api_Backups_Utility::format_timestamp( intval( $backup->expires_at / 1000 ) );
1428 823
1429 - if ( '200' !== $httpcode ) {
1430 - return false;
1431 - }
1432 - curl_close( $ch );
1433 - return json_decode( $output );
1434 - }
824 + // Check if backup is expired, disable row including download button.
825 + if ( intval( $backup->expires_at / 1000 ) > time() ) {
1435 826
1436 - /**
1437 - * Fetch Cloudways oAuth Access Token.
1438 - *
1439 - * Fetch the Cloudways oAuth access token from the given API credentials.
1440 - *
1441 - * @return mixed Return Cloudways Access Token.
1442 - */
1443 - public static function fetch_cloudways_access_token() {
1444 - $account_email = get_option( 'mainwp_cloudways_api_account_email' );
1445 - $api_key = self::get_cloudways_api_key();
827 + ?>
1446 828
1447 - // Fetch Access Token.
1448 - $tokenResponse = self::call_cloudways_api(
1449 - 'POST',
1450 - '/oauth/access_token',
1451 - null,
1452 - array(
1453 - 'email' => $account_email,
1454 - 'api_key' => $api_key,
1455 - )
1456 - );
1457 - if ( empty( $tokenResponse ) ) {
1458 - return;
1459 - }
1460 - return $tokenResponse->access_token;
1461 - }
829 + <tr>
830 + <td class="collapsing"><?php echo esc_html( $created_date ); ?></td>
831 + <td class="collapsing"><?php echo esc_html( $expiry_date ); ?></td>
832 + <td>
833 + <a class="kinsta_download" href="<?php echo esc_attr( $backup->download_link ); ?>" target="_blank">
834 + <button class="ui right labeled icon button">
835 + <i class="right download icon"></i>
836 + <?php echo esc_html__( 'Download', 'mainwp' ); ?>
837 + </button>
838 + </a>
839 + </td>
840 + </tr>
841 + <?php } else { ?>
842 + <tr class="disabled">
843 + <td class="collapsing"><?php echo esc_html( $created_date ); ?></td>
844 + <td class="collapsing"><?php echo esc_html( $expiry_date ); ?></td>
845 + <td>
846 + <a class="kinsta_download" href="<?php echo esc_attr( $backup->download_link ); ?>" target="_blank">
847 + <button class="ui right labeled icon button disabled">
848 + <i class="right download icon"></i>
849 + <?php echo esc_html__( 'Download', 'mainwp' ); ?>
850 + </button>
851 + </a>
852 + </td>
853 + </tr>
854 + <?php } ?>
855 + <?php } ?>
856 + <?php } ?>
857 + </tbody>
858 + <tfoot>
859 + <tr>
860 + <th scope="col"><?php esc_html_e( 'Created', 'mainwp' ); ?></th>
861 + <th scope="col"><?php esc_html_e( 'Expiry', 'mainwp' ); ?></th>
862 + <th scope="col" class="no-sort collapsing"></th>
863 + </tr>
864 + </tfoot>
865 + </table>
866 + <?php } ?>
867 + <?php // Display Plesk Table. ?>
868 + <?php
869 + if ( 'plesk' === $backup_api ) {
870 + // Grab available cPanel Automatic Backups or set to empty array.
871 + if ( is_object( $available_backups ) && isset( $available_backups->value ) ) {
872 + $available_backups = $available_backups->value;
873 + } else {
874 + $available_backups = array();
875 + }
876 + ?>
877 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
878 + <thead>
879 + <tr>
880 + <th scope="col"><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
881 + <th scope="col"><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
882 + <th scope="col" class="no-sort collapsing"></th>
883 + <th scope="col" class="no-sort collapsing"></th>
884 + </tr>
885 + </thead>
886 + <tbody>
887 + <?php foreach ( $available_backups as $backup ) { ?>
888 + <?php
889 + $backup_date = gmdate( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $backup->value->createdAt->value ) );
1462 890
1463 - /**
1464 - * Fetch all available servers.
1465 - *
1466 - * @return mixed Returns available list of servers.
1467 - */
1468 - public static function fetch_cloudways_server_list() {
1469 - // Grab access token.
1470 - $accessToken = self::fetch_cloudways_access_token();
891 + $opts = Api_Backups_Helper::get_website_options(
892 + $website['id'],
893 + array(
894 + 'mainwp_plesk_installation_id', // Plesk installation id.
895 + )
896 + );
1471 897
1472 - // Fetch Server List.
1473 - $serverList = (array) self::call_cloudways_api( 'GET', '/server', $accessToken );
1474 - if ( ! array_key_exists( 'servers', $serverList ) ) {
1475 - return;
1476 - }
1477 - // Return the server list.
1478 - return $serverList['servers'];
1479 - }
898 + if ( is_array( $opts ) ) {
899 + $installation_id = $opts['mainwp_plesk_installation_id'] ?? '';
900 + }
901 + ?>
902 + <tr>
903 + <td class="collapsing"><?php echo esc_html( $backup->value->fileName->value ); ?></td>
904 + <td class="collapsing"><?php echo esc_html( $backup_date ); ?></td>
905 + <td></td>
906 + <td class="collapsing right aligned">
907 + <button id="plesk_restore_button" class="ui circular mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup item"
908 + installation_id="<?php echo intval( $installation_id ); ?>"
909 + website_id="<?php echo intval( $website['id'] ); ?>"
910 + backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
911 + data-tooltip="<?php esc_attr_e( 'Restore Backup', 'mainwp' ); ?>"
912 + data-inverted=""
913 + data-position="top center">
914 + <i class="undo icon"></i>
915 + </button>
916 + <?php
917 + /**
918 + * Grab installation domain & build path to download.
919 + * Eg.: /var/www/vhosts/example.com/wordpress-backups/
920 + */
921 + $installation_domain = static::get_plesk_home_dir();
922 + $dirdl = '/var/www/vhosts/' . $installation_domain . '/wordpress-backups/';
923 + ?>
1480 924
925 + <a id="plesk_download_button" class="ui circular mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_downlaod_backup item"
926 + installation_id="<?php echo intval( $installation_id ); ?>"
927 + website_id="<?php echo intval( $website['id'] ); ?>"
928 + backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
929 + href="<?php MainWP_Site_Open::get_open_site_admin_link( $website['id'], true ); //phpcs:ignore -- ok. ?>&dirdl=<?php echo esc_attr( rawurlencode( $dirdl ) ); ?>&filedl=<?php echo esc_attr( rawurlencode( $backup->value->fileName->value ) ); ?>"
930 + data-tooltip="<?php esc_attr_e( 'Download Backup', 'mainwp' ); ?>"
931 + data-inverted=""
932 + data-position="top center"
933 + target="_blank">
934 + <i class="download icon"></i>
935 + </a>
936 + <button id="plesk_delete_button" class="ui circular mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup item"
937 + installation_id="<?php echo intval( $installation_id ); ?>"
938 + website_id="<?php echo intval( $website['id'] ); ?>"
939 + backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
940 + data-tooltip="<?php esc_attr_e( 'Delete Backup', 'mainwp' ); ?>"
941 + data-inverted=""
942 + data-position="top center">
943 + <i class="trash icon"></i>
944 + </button>
945 + </td>
946 + </tr>
947 + <?php } ?>
948 + </tbody>
949 + <tfoot>
950 + <tr>
951 + <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
952 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
953 + <th scope="col" class="no-sort collapsing"></th>
954 + <th scope="col" class="no-sort collapsing"></th>
955 + </tr>
956 + </tfoot>
957 + </table>
958 + <?php } ?>
959 + <?php // Display cPanel Table. ?>
960 + <?php
961 + if ( 'cpanel' === $backup_api ) {
1481 962
1482 - /**
1483 - * Ajax.
1484 - * Save the server & app ID to that Child Site's options table.
1485 - *
1486 - * Compare connected Child Sites against connected Cloudways account.
1487 - * Automatically check for Child Sites domain name in server list & save.
1488 - * that app's Server ID & App ID to that Child Site's options table.
1489 - */
1490 - public function ajax_cloudways_action_update_ids() {
1491 - Api_Backups_Helper::security_nonce( 'cloudways_action_update_ids' );
1492 - self::cloudways_action_update_ids();
1493 - }
963 + // Grab available cPanel Automatic Backups or set to empty array.
964 + if ( is_object( $available_backups ) && isset( $available_backups->data ) ) {
965 + $available_backups_automatic_list = $available_backups->data;
966 + } else {
967 + $available_backups_automatic_list = array();
968 + }
1494 969
1495 - /**
1496 - * Save the server & app ID to that Child Site's options table.
1497 - *
1498 - * Compare connected Child Sites against connected Cloudways account.
1499 - * Automatically check for Child Sites domain name in server list & save.
1500 - * that app's Server ID & App ID to that Child Site's options table.
1501 - */
1502 - public static function cloudways_action_update_ids() {
1503 - // Fetch Child Site domains.
1504 - $child_sites = array();
1505 - $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
970 + // Grab available cPanel Manual Backups.
971 + $available_backups_manual_list = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ) );
1506 972
1507 - foreach ( $websites as $website ) {
1508 - $child_sites[ $website['id'] ] = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', urldecode( $website['url'] ) ) );
1509 - }
973 + // Check if valid JSON or not. If not, then it's a string - do not decode it.
974 + if ( isset( $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ] ) && ! empty( $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ] ) ) {
975 + json_decode( $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ] );
976 + if ( json_last_error() === JSON_ERROR_NONE ) {
977 + // JSON is valid.
978 + $available_backups_manual_list = json_decode( $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ] );
979 + } else {
980 + // JSON is invalid treat it as a string.
981 + $available_backups_manual_list = $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ];
982 + }
983 + } else {
984 + $available_backups_manual_list = array();
985 + }
1510 986
1511 - // Fetch Cloudways Server List.
1512 - $server_list = self::fetch_cloudways_server_list();
987 + // Grab available cPanel Manual Database Backups.
988 + $mainwp_3rd_party_cpanel_manual_database_backups = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ) );
1513 989
1514 - /**
1515 - * Search $server_list for Child Site app ID & server ID.
1516 - *
1517 - * Loop through each Server/App & check if app cname / fqdn name matches any Child Site domain name.
1518 - * if so, save the server & app ID to that Child Site's options table.
1519 - */
1520 - if ( ! is_array( $server_list ) ) {
1521 - return;
1522 - }
1523 - foreach ( $server_list as $server ) {
1524 - foreach ( $server->apps as $app ) {
1525 - if ( in_array( $app->cname, $child_sites ) ) {
1526 - $found_child_site_id = array_search( $app->cname, $child_sites );
1527 - // Update Child Site options table.
1528 - Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_app_id', $app->id );
1529 - Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_instance_id', $app->server_id );
1530 - Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_api', 'Cloudways' );
1531 - } 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.
1532 - $found_child_site_id = array_search( $app->app_fqdn, $child_sites );
1533 - // Update Child Site options table.
1534 - Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_app_id', $app->id );
1535 - Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_instance_id', $app->server_id );
1536 - Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_api', 'Cloudways' );
1537 - }
1538 - }
1539 - }
1540 - }
990 + // Check if valid JSON or not. If not, then it's a string - do not decode it.
991 + if ( isset( $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ] ) && ! empty( $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ] ) ) {
992 + json_decode( $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ] );
993 + if ( json_last_error() === JSON_ERROR_NONE ) {
994 + // JSON is valid.
995 + $available_manual_database_backups = json_decode( $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ] );
996 + } else {
997 + // JSON is invalid treat it as a string.
998 + $available_manual_database_backups = $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ];
999 + }
1000 + } else {
1001 + $available_manual_database_backups = array();
1002 + }
1003 + ?>
1004 + <div class="ui bottom attached active tab" data-tab="cpanel-native">
1005 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1006 + <thead>
1007 + <tr>
1008 + <th scope="col" colspan="4">
1009 + <?php esc_html_e( 'Automatic Host Backups', 'mainwp' ); ?>
1010 + </th>
1011 + </tr>
1012 + <tr>
1013 + <th scope="col"><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1014 + <th scope="col"><?php esc_html_e( 'Backup Type', 'mainwp' ); ?></th>
1015 + <th scope="col"><?php esc_html_e( 'Site Path', 'mainwp' ); ?></th>
1016 + <th scope="col" class="no-sort collapsing"></th>
1017 + </tr>
1018 + </thead>
1019 + <tbody>
1020 + <?php foreach ( $available_backups_automatic_list as $backup ) { ?>
1021 + <tr>
1022 + <td><?php echo esc_html( $backup->backupID ); ?></td>
1023 + <td><?php echo esc_html( ucfirst( $backup->backupType ) ); ?></td>
1024 + <td><?php echo esc_html( $backup->path ); ?></td>
1025 + <td>
1026 + <a id="cpanel_automatic_backup_button" class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup item"
1027 + website_id="<?php echo intval( $website['id'] ); ?>"
1028 + backup_type="<?php echo esc_attr( 'automatic' ); ?>"
1029 + backup_path="<?php echo esc_attr( $backup->path ); ?>"
1030 + backup_name="<?php echo esc_attr( $backup->backupID ); ?>"
1031 + href="javascript:void(0)">
1032 + <button class="ui right labeled icon button">
1033 + <i class="right undo icon"></i>
1034 + <?php esc_html_e( 'Restore', 'mainwp' ); ?>
1035 + </button>
1036 + </a>
1037 + </td>
1038 + </tr>
1039 + <?php } ?>
1040 + </tbody>
1041 + <tfoot>
1042 + <tr>
1043 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1044 + <th scope="col" ><?php esc_html_e( 'Backup Type', 'mainwp' ); ?></th>
1045 + <th scope="col" ><?php esc_html_e( 'Site Path', 'mainwp' ); ?></th>
1046 + <th scope="col" class="no-sort collapsing"></th>
1047 + </tr>
1048 + </tfoot>
1049 + </table>
1050 + <div class="ui divider hidden"></div>
1051 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1052 + <thead>
1053 + <tr>
1054 + <th scope="col" colspan="3">
1055 + <div class="ui equal width grid">
1056 + <div class="left aligned middle aligned column">
1057 + <?php esc_html_e( 'Manual Account Backups', 'mainwp' ); ?>
1058 + </div>
1059 + <div class="right aligned middle aligned column">
1060 + <?php
1061 + $el_id_cp_api = $backup_api;
1062 + ?>
1063 + <button id="mainwp_3rd_party_api_<?php echo esc_attr( $el_id_cp_api ); ?>_action_individual_create_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui primary elastic green button"><?php esc_html_e( 'Backup', 'mainwp' ); ?></button>
1064 + </div>
1065 + </div>
1066 + </th>
1067 + </tr>
1068 + <tr>
1069 + <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1070 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1071 + <th scope="col" class="no-sort collapsing"></th>
1072 + </tr>
1073 + </thead>
1074 + <tbody>
1075 + <?php foreach ( $available_backups_manual_list as $backup ) { ?>
1076 + <?php
1077 + $my_unix_timestamp = $backup->timestamp;
1078 + $backup_date = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $my_unix_timestamp ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
1079 + ?>
1080 + <tr>
1081 + <td class="collapsing"><?php echo esc_html( $backup->file_name ); ?></td>
1082 + <td class="collapsing"><?php echo esc_html( $backup_date ); ?></td>
1083 + <td>
1084 + <?php
1085 + $file_path = $backup->absolute_dir . '/';
1086 + ?>
1087 + <a class="open_newwindow_wpadmin" href="<?php MainWP_Site_Open::get_open_site_admin_link( $website['id'], true ); //phpcs:ignore -- ok. ?>&dirdl=<?php echo esc_attr( rawurlencode( $file_path ) ); ?>&filedl=<?php echo esc_attr( rawurlencode( $backup->file_name ) ); ?>" target="_blank">
1088 + <button class="ui right labeled icon button">
1089 + <i class="right download icon"></i>
1090 + <?php echo esc_html__( 'Download', 'mainwp' ); ?>
1091 + </button>
1092 + </a>
1093 + </td>
1094 + </tr>
1095 + <?php } ?>
1096 + </tbody>
1097 + <tfoot>
1098 + <tr>
1099 + <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1100 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1101 + <th scope="col" class="no-sort collapsing"></th>
1102 + </tr>
1103 + </tfoot>
1104 + </table>
1105 + <div class="ui divider hidden"></div>
1106 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1107 + <thead>
1108 + <tr>
1109 + <th scope="col" colspan="3">
1110 + <div class="ui equal width grid">
1111 + <div class="left aligned middle aligned column">
1112 + <?php esc_html_e( 'Manual Database Backups', 'mainwp' ); ?>
1113 + </div>
1114 + <div class="right aligned middle aligned column">
1115 + <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_create_database_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui primary elastic green button"><?php esc_html_e( 'Backup', 'mainwp' ); ?></button>
1116 + </div>
1117 + </div>
1118 + </th>
1119 + </tr>
1120 + <tr>
1121 + <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1122 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1123 + <th scope="col" class="no-sort collapsing"></th>
1124 + </tr>
1125 + </thead>
1126 + <tbody>
1127 + <?php foreach ( $available_manual_database_backups as $backup ) { ?>
1128 + <?php
1129 + $my_unix_timestamp = $backup->timestamp;
1130 + $backup_date = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $my_unix_timestamp ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
1131 + ?>
1132 + <tr>
1133 + <td class="collapsing"><?php echo esc_html( $backup->file_name ); ?></td>
1134 + <td class="collapsing"><?php echo esc_html( $backup_date ); ?></td>
1135 + <td>
1136 + <a id="database_backup_button" class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_database_backup item"
1137 + website_id="<?php echo intval( $website['id'] ); ?>"
1138 + backup_path="<?php echo esc_attr( $backup->absolute_dir ); ?>"
1139 + backup_name="<?php echo esc_attr( $backup->file_name ); ?>"
1140 + href="javascript:void(0)">
1141 + <button class="ui right labeled icon button">
1142 + <i class="right undo icon"></i>
1143 + <?php esc_html_e( 'Restore', 'mainwp' ); ?>
1144 + </button>
1145 + </a>
1146 + </td>
1147 + </tr>
1148 + <?php } ?>
1149 + </tbody>
1150 + <tfoot>
1151 + <tr>
1152 + <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1153 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1154 + <th scope="col" class="no-sort collapsing"></th>
1155 + </tr>
1156 + </tfoot>
1157 + </table>
1158 + </div>
1159 + <div class="ui bottom attached tab" data-tab="cpanel-wp-toolkit">
1160 + <?php
1161 + $available_wptk_backups = array();
1162 + /**
1163 + * Grab WP-Toolkit status & available backups.
1164 + */
1165 + $mainwp_enable_wp_toolkit = '0'; // Default to false.
1541 1166
1167 + if ( is_array( $website ) && key_exists( 'id', $website ) ) {
1168 + // Grab given website options.
1169 + $opts = Api_Backups_Helper::get_website_options(
1170 + $website['id'],
1171 + array(
1172 + 'mainwp_enable_wp_toolkit', // WP-Toolkit status.
1173 + 'mainwp_3rd_party_cpanel_wp_toolkit_backups', // WP-Toolkit backups.
1174 + )
1175 + );
1542 1176
1543 - /**
1544 - * Cloudways: action backup.
1545 - *
1546 - * Perform a backup on the selected Cloudways server.
1547 - *
1548 - * @return void
1549 - */
1550 - public function ajax_cloudways_action_individual_backup() {
1551 - Api_Backups_Helper::security_nonce( 'cloudways_action_individual_backup' );
1552 - self::cloudways_action_backup();
1553 - }
1177 + if ( is_array( $opts ) ) {
1178 + // Grab WP-Toolkit status.
1179 + $mainwp_enable_wp_toolkit = $opts['mainwp_enable_wp_toolkit'] ?? '0';
1554 1180
1555 - /**
1556 - * Cloudways: action backup.
1557 - *
1558 - * Perform a backup on the selected Cloudways server.
1559 - *
1560 - * @return void
1561 - */
1562 - public function ajax_cloudways_action_backup() {
1563 - Api_Backups_Helper::security_nonce( 'cloudways_action_backup' );
1564 - self::cloudways_action_create_backup();
1565 - }
1181 + // Grab WP-Toolkit backups.
1182 + $cpanel_wp_toolkit_backups = ! empty( $opts['mainwp_3rd_party_cpanel_wp_toolkit_backups'] ) ? json_decode( $opts['mainwp_3rd_party_cpanel_wp_toolkit_backups'] ) : false;
1183 + $available_wptk_backups = is_object( $cpanel_wp_toolkit_backups ) && ! empty( $cpanel_wp_toolkit_backups->value ) ? $cpanel_wp_toolkit_backups->value : false;
1184 + }
1185 + }
1186 + ?>
1187 + <?php if ( $mainwp_enable_wp_toolkit ) : // Display WP-Toolkit Table if enabled. ?>
1188 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-wptk-table" class="ui mainwp-api-backup-table table" style="width:100%">
1189 + <thead>
1190 + <tr>
1191 + <th scope="col" colspan="4">
1192 + <?php esc_html_e( 'WP Toolkit Backups', 'mainwp' ); ?>
1193 + </th>
1194 + </tr>
1195 + <tr>
1196 + <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1197 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1198 + <th scope="col" class="no-sort collapsing"></th>
1199 + <th scope="col" class="no-sort collapsing"></th>
1200 + </tr>
1201 + </thead>
1202 + <tbody>
1203 + <?php
1204 + if ( ! is_array( $available_wptk_backups ) ) {
1205 + $available_wptk_backups = array();
1206 + }
1207 + foreach ( $available_wptk_backups as $backup ) {
1208 + ?>
1209 + <?php
1210 + $my_unix_timestamp = strtotime( $backup->value->createdAt->value );
1211 + $backup_date = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $my_unix_timestamp ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
1212 + ?>
1213 + <tr>
1214 + <td class=""><?php echo esc_html( $backup->value->fileName->value ); ?></td>
1215 + <td class=""><?php echo esc_html( $backup_date ); ?></td>
1216 + <td></td>
1217 + <td class="right aligned">
1218 + <button class="ui mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_wptk_backup item"
1219 + website_id="<?php echo intval( $website['id'] ); ?>"
1220 + backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
1221 + data-tooltip="<?php esc_attr_e( 'Restore Backup', 'mainwp' ); ?>"
1222 + data-inverted=""
1223 + data-position="top center">
1224 + <i class="undo icon"></i>
1225 + </button>
1226 + <?php
1227 + /**
1228 + * Grab home directory & build download directory.
1229 + * Eg.: /home/cpanel_username/wordpress-backups/
1230 + */
1231 + $home_dir = static::cpanel_action_get_home_directory();
1232 + $dirdl = $home_dir . '/wordpress-backups/';
1233 + ?>
1234 + <button class="ui mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_download_wptk_backup item"
1235 + website_id="<?php echo intval( $website['id'] ); ?>"
1236 + backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
1237 + href="<?php MainWP_Site_Open::get_open_site_admin_link( $website['id'], true ); //phpcs:ignore -- ok. ?>&dirdl=<?php echo esc_attr( rawurlencode( $dirdl ) ); ?>&filedl=<?php echo esc_attr( rawurlencode( $backup->value->fileName->value ) ); ?>"
1238 + data-tooltip="<?php esc_attr_e( 'Download Backup', 'mainwp' ); ?>"
1239 + data-inverted=""
1240 + data-position="top center">
1241 + <i class="download icon"></i>
1242 + </button>
1243 + <button class="ui mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_wptk_backup item"
1244 + website_id="<?php echo intval( $website['id'] ); ?>"
1245 + backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
1246 + data-tooltip="<?php esc_attr_e( 'Delete Backup', 'mainwp' ); ?>"
1247 + data-inverted=""
1248 + data-position="top center">
1249 + <i class="trash icon"></i>
1250 + </button>
1251 + </td>
1252 + </tr>
1253 + <?php } ?>
1254 + </tbody>
1255 + <tfoot>
1256 + <tr>
1257 + <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1258 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1259 + <th scope="col" class="no-sort collapsing"></th>
1260 + <th scope="col" class="no-sort collapsing"></th>
1261 + </tr>
1262 + </tfoot>
1263 + </table>
1264 + <?php else : // Display message if WP-Toolkit is not enabled. ?>
1265 + <?php
1266 + $title = esc_html__( 'The WP-Toolkit API has not been enabled.', 'mainwp' );
1267 + $message = esc_html__( 'Please double check that you have set the cPanel API Key on the API Backups Settings page and have enabled the WP Toolkit API on the Child Site -> Edit page.', 'mainwp' );
1268 + $icon = '<em data-emoji=":closed_lock_with_key:" class="big"></em>';
1269 + \MainWP\Dashboard\MainWP_UI::render_empty_page_placeholder( $title, $message, $icon );
1270 + ?>
1271 + <?php endif; ?>
1272 + </div>
1273 + <?php } ?>
1274 + <?php // Display GridPane Table. ?>
1275 + <?php
1276 + if ( 'gridpane' === $backup_api ) {
1277 + if ( isset( $available_backups->automatic ) ) {
1278 + $available_backups_automatic_list = explode( ',', $available_backups->automatic );
1279 + } else {
1280 + $available_backups_automatic_list = array();
1281 + }
1282 + if ( isset( $available_backups->manual ) ) {
1283 + $available_backups_manual_list = explode( ',', $available_backups->manual );
1284 + } else {
1285 + $available_backups_manual_list = array();
1286 + }
1287 + ?>
1288 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1289 + <thead>
1290 + <tr>
1291 + <th scope="col" ><?php esc_html_e( 'GridPane Backup Name', 'mainwp' ); ?></th>
1292 + <th scope="col" ><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
1293 + <th scope="col" class="no-sort collapsing"></th>
1294 + <th scope="col" class="no-sort collapsing"></th>
1295 + </tr>
1296 + </thead>
1297 + <tbody>
1298 + <?php foreach ( $available_backups_automatic_list as $backup ) { ?>
1299 + <tr>
1300 + <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup ); ?></td>
1301 + <td><?php esc_html_e( 'Automatic', 'mainwp' ); ?></td>
1302 + <td></td>
1303 + <td class="collapsing right aligned">
1304 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1305 + website_id="<?php echo intval( $website['id'] ); ?>"
1306 + backup_type="<?php echo esc_attr( 'automatic' ); ?>"
1307 + backup_name="<?php echo esc_attr( $backup ); ?>"
1308 + href="javascript:void(0)">
1309 + <i class="undo icon"></i>
1310 + </a>
1311 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button"
1312 + website_id="<?php echo intval( $website['id'] ); ?>"
1313 + backup_type="<?php echo esc_attr( 'automatic' ); ?>"
1314 + backup_name="<?php echo esc_attr( $backup ); ?>"
1315 + href="javascript:void(0)">
1316 + <i class="trash icon"></i>
1317 + </a>
1318 + </td>
1319 + </tr>
1320 + <?php } ?>
1321 + <?php foreach ( $available_backups_manual_list as $backup ) { ?>
1322 + <tr>
1323 + <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup ); ?></td>
1324 + <td><?php esc_html_e( 'Manual', 'mainwp' ); ?></td>
1325 + <td></td>
1326 + <td class="collapsing right aligned">
1327 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1328 + website_id="<?php echo intval( $website['id'] ); ?>"
1329 + backup_type="<?php echo esc_attr( 'manual' ); ?>"
1330 + backup_name="<?php echo esc_attr( $backup ); ?>"
1331 + href="javascript:void(0)">
1332 + <i class="undo icon"></i>
1333 + </a>
1334 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button"
1335 + website_id="<?php echo intval( $website['id'] ); ?>"
1336 + backup_type="<?php echo esc_attr( 'manual' ); ?>"
1337 + backup_name="<?php echo esc_attr( $backup ); ?>"
1338 + href="javascript:void(0)">
1339 + <i class="trash icon"></i>
1340 + </a>
1341 + </td>
1342 + </tr>
1343 + <?php } ?>
1344 + </tbody>
1345 + <tfoot>
1346 + <tr>
1347 + <th scope="col" ><?php esc_html_e( 'GridPane Backup Name', 'mainwp' ); ?></th>
1348 + <th scope="col" ><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
1349 + <th scope="col" class="no-sort collapsing"></th>
1350 + <th scope="col" class="no-sort collapsing"></th>
1351 + </tr>
1352 + </tfoot>
1353 + </table>
1354 + <?php } ?>
1355 + <?php // Display Cloudways Table. ?>
1356 + <?php
1357 + if ( 'cloudways' === $backup_api ) {
1566 1358
1567 - /**
1568 - * Cloudways: action backup.
1569 - *
1570 - * Perform a backup on the selected Cloudways server.
1571 - *
1572 - * @param int $website_id Website ID.
1573 - * @param bool $ret_val Return output or not.
1574 - *
1575 - * @return mixed
1576 - */
1577 - public static function cloudways_action_create_backup( $website_id = '', $ret_val = false ) {
1359 + // Check if backups are available.
1360 + if ( isset( $available_backups->application_backup_exists ) && true === $available_backups->application_backup_exists ) {
1361 + $available_backups = $available_backups->backup_dates;
1362 + } else {
1363 + $available_backups = array();
1364 + }
1578 1365
1579 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : $website_id; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
1366 + ?>
1367 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1368 + <thead>
1369 + <tr>
1370 + <th scope="col" ><?php esc_html_e( 'Cloudways Backup Type', 'mainwp' ); ?></th>
1371 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1372 + <th scope="col" class="no-sort collapsing"></th>
1373 + <th scope="col" class="no-sort collapsing"></th>
1374 + </tr>
1375 + </thead>
1376 + <tbody>
1377 + <?php foreach ( $available_backups as $backup ) { ?>
1378 + <tr>
1379 + <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php esc_html_e( 'Application Backup', 'mainwp' ); ?></td>
1380 + <td><?php echo esc_html( gmdate( 'm-d-Y ( h:i:s )', strtotime( $backup ) ) ); ?></td>
1381 + <td></td>
1382 + <td>
1383 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button" website_id="<?php echo intval( $website['id'] ); ?>" backup_date="<?php echo esc_attr( $backup ); ?>" href="javascript:void(0)"><i class="undo icon"></i></a>
1384 + </td>
1385 + </tr>
1386 + <?php } ?>
1387 + </tbody>
1388 + <tfoot>
1389 + <tr>
1390 + <th scope="col" ><?php esc_html_e( 'Cloudways Backup Type', 'mainwp' ); ?></th>
1391 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1392 + <th scope="col" class="no-sort collapsing"></th>
1393 + <th scope="col" class="no-sort collapsing"></th>
1394 + </tr>
1395 + </tfoot>
1396 + </table>
1397 + <?php } ?>
1398 + <?php // Display Vultr Table. ?>
1399 + <?php
1400 + if ( 'vultr' === $backup_api ) {
1401 + if ( isset( $available_backups->snapshots ) ) {
1402 + $available_snapshots_list = $available_backups->snapshots;
1403 + } else {
1404 + $available_snapshots_list = array();
1405 + }
1406 + if ( isset( $available_backups->backups ) ) {
1407 + $available_backups_list = $available_backups->backups;
1408 + } else {
1409 + $available_backups_list = array();
1410 + }
1411 + ?>
1412 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1413 + <thead>
1414 + <tr>
1415 + <th scope="col" ><?php esc_html_e( 'Vultr Backup Label', 'mainwp' ); ?></th>
1416 + <th scope="col" ><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1417 + <th scope="col" ><?php esc_html_e( 'Compressed Size', 'mainwp' ); ?></th>
1418 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1419 + <th scope="col" ><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1420 + <th scope="col" class="no-sort collapsing"></th>
1421 + <th scope="col" class="no-sort collapsing"></th>
1422 + </tr>
1423 + </thead>
1424 + <tbody>
1425 + <?php
1426 + foreach ( $available_snapshots_list as $backup ) {
1427 + if ( empty( $backup ) || ! is_object( $backup ) || empty( $backup->date_created ) ) {
1428 + continue;
1429 + }
1430 + ?>
1431 + <tr>
1432 + <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->description ); ?></td>
1433 + <td><?php echo esc_html( Api_Backups_Utility::human_filesize( $backup->size ) ); ?></td>
1434 + <td><?php echo esc_html( Api_Backups_Utility::human_filesize( $backup->compressed_size ) ); ?></td>
1435 + <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->date_created ) ) ); ?></td>
1436 + <td><?php echo esc_html( $backup->status ); ?></td>
1437 + <td></td>
1438 + <td class="collapsing right aligned">
1439 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button" website_id="<?php echo intval( $website['id'] ); ?>" snapshot_id="<?php echo esc_attr( $backup->id ); ?>" href="javascript:void(0)"><i class="undo icon"></i></a>
1440 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button" website_id="<?php echo intval( $website['id'] ); ?>" snapshot_id="<?php echo esc_attr( $backup->id ); ?>" href="javascript:void(0)"><i class="trash icon"></i></a>
1441 + </td>
1442 + </tr>
1443 + <?php } ?>
1444 + <?php
1445 + foreach ( $available_backups_list as $backup ) {
1446 + if ( empty( $backup ) || ! is_object( $backup ) || empty( $backup->date_created ) ) {
1447 + continue;
1448 + }
1449 + ?>
1450 + <tr>
1451 + <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->description ); ?></td>
1452 + <td><?php echo esc_html( Api_Backups_Utility::human_filesize( $backup->size ) ); ?></td>
1453 + <td><?php esc_html_e( 'N/A', 'mainwp' ); ?></td>
1454 + <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->date_created ) ) ); ?></td>
1455 + <td><?php echo esc_html( $backup->status ); ?></td>
1456 + <td></td>
1457 + <td class="collapsing right aligned">
1458 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1459 + website_id="<?php echo intval( $website['id'] ); ?>"
1460 + snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1461 + href="javascript:void(0)">
1462 + <i class="undo icon"></i>
1463 + </a>
1464 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button"
1465 + website_id="<?php echo intval( $website['id'] ); ?>"
1466 + snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1467 + href="javascript:void(0)">
1468 + <i class="trash icon"></i>
1469 + </a>
1470 + </td>
1471 + </tr>
1472 + <?php } ?>
1473 + </tbody>
1474 + <tfoot>
1475 + <tr>
1476 + <th scope="col" ><?php esc_html_e( 'Vultr Backup Label', 'mainwp' ); ?></th>
1477 + <th scope="col" ><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1478 + <th scope="col" ><?php esc_html_e( 'Compressed Size', 'mainwp' ); ?></th>
1479 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1480 + <th scope="col" ><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1481 + <th scope="col" class="no-sort collapsing"></th>
1482 + <th scope="col" class="no-sort collapsing"></th>
1483 + </tr>
1484 + </tfoot>
1485 + </table>
1486 + <?php } ?>
1487 + <?php // Display Linode Table. ?>
1488 + <?php
1489 + if ( 'linode' === $backup_api ) {
1580 1490
1581 - // Grab this from websites.
1582 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_app_id' ) );
1583 - $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
1584 - $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
1491 + // Automatic Backups.
1492 + if ( isset( $available_backups->automatic ) ) {
1493 + $available_backups_automatic_list = $available_backups->automatic;
1494 + } else {
1495 + $available_backups_automatic_list = array();
1496 + }
1585 1497
1586 - $data = array(
1587 - 'server_id' => $server_id,
1588 - 'app_id' => $app_id,
1589 - );
1498 + // Manual Backups.
1499 + if ( isset( $available_backups->snapshot ) ) {
1500 + $available_backups_snapshot_list = $available_backups->snapshot;
1501 + } else {
1502 + $available_backups_snapshot_list = array();
1503 + }
1504 + ?>
1505 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1506 + <thead>
1507 + <tr>
1508 + <th scope="col" ><?php esc_html_e( 'Akamai (Linode) Backup Type', 'mainwp' ); ?></th>
1509 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1510 + <th scope="col" ><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1511 + <th scope="col" class="no-sort collapsing"></th>
1512 + <th scope="col" class="no-sort collapsing"></th>
1513 + <th scope="col" class="no-sort collapsing"></th>
1514 + </tr>
1515 + </thead>
1516 + <tbody>
1517 + <?php foreach ( $available_backups_automatic_list as $backup ) { ?>
1518 + <tr>
1519 + <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->type ); ?></td>
1520 + <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->created ) ) ); ?></td>
1521 + <td class="operation_status"><?php echo esc_html( $backup->status ); ?></td>
1522 + <td></td>
1523 + <td></td>
1524 + <td>
1525 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1526 + website_id="<?php echo intval( $website['id'] ); ?>"
1527 + backup_type="<?php echo esc_attr( $backup->type ); ?>"
1528 + backup_id="<?php echo esc_attr( $backup->id ); ?>"
1529 + href="javascript:void(0)">
1530 + <i class="undo icon"></i>
1531 + </a>
1532 + </td>
1533 + </tr>
1534 + <?php } ?>
1535 + <?php foreach ( $available_backups_snapshot_list as $backup ) { ?>
1536 + <?php if ( null !== $backup ) { ?>
1537 + <tr>
1538 + <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->type ); ?></td>
1539 + <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->created ) ) ); ?></td>
1540 + <td><?php echo esc_html( $backup->status ); ?></td>
1541 + <td></td>
1542 + <td></td>
1543 + <td>
1590 1544
1591 - // Grab Cloudways access token.
1592 - $accessToken = self::fetch_cloudways_access_token();
1545 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1546 + website_id="<?php echo intval( $website['id'] ); ?>"
1547 + backup_type="<?php echo esc_attr( $backup->type ); ?>"
1548 + backup_id="<?php echo esc_attr( $backup->id ); ?>"
1549 + href="javascript:void(0)">
1550 + <i class="undo icon"></i>
1551 + </a>
1552 + </td>
1553 + </tr>
1554 + <?php } ?>
1555 + <?php } ?>
1556 + </tbody>
1557 + <tfoot>
1558 + <tr>
1559 + <th scope="col" ><?php esc_html_e( 'Akamai (Linode) Backup Type', 'mainwp' ); ?></th>
1560 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1561 + <th scope="col" ><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1562 + <th scope="col" class="no-sort collapsing"></th>
1563 + <th scope="col" class="no-sort collapsing"></th>
1564 + <th scope="col" class="no-sort collapsing"></th>
1565 + </tr>
1566 + </tfoot>
1567 + </table>
1568 + <?php } ?>
1569 + <?php // Display DigitalOcean Table. ?>
1570 + <?php
1571 + if ( 'digitalocean' === $backup_api ) {
1572 + if ( isset( $available_backups->snapshots ) ) {
1573 + $available_backups = $available_backups->snapshots;
1574 + }
1575 + if ( ! is_array( $available_backups ) ) {
1576 + $available_backups = array();
1577 + }
1578 + ?>
1579 + <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1580 + <thead>
1581 + <tr>
1582 + <th scope="col" ><?php esc_html_e( 'DigitalOcean Backup Label', 'mainwp' ); ?></th>
1583 + <th scope="col" ><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1584 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1585 + <th scope="col" class="no-sort collapsing"></th>
1586 + <th scope="col" class="no-sort collapsing"></th>
1587 + </tr>
1588 + </thead>
1589 + <tbody>
1590 + <?php foreach ( $available_backups as $backup ) { ?>
1591 + <tr>
1592 + <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->name ); ?></td>
1593 + <td><?php echo intval( $backup->size_gigabytes ); ?>GB</td>
1594 + <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->created_at ) ) ); ?></td>
1595 + <td></td>
1596 + <td class="collapsing right aligned">
1597 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1598 + website_id="<?php echo intval( $website['id'] ); ?>"
1599 + snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1600 + href="javascript:void(0)">
1601 + <i class="undo icon"></i>
1602 + </a>
1603 + <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button"
1604 + website_id="<?php echo intval( $website['id'] ); ?>"
1605 + snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1606 + href="javascript:void(0)">
1607 + <i class="trash icon"></i>
1608 + </a>
1609 + </td>
1610 + </tr>
1611 + <?php } ?>
1612 + </tbody>
1613 + <tfoot>
1614 + <tr>
1615 + <th scope="col" ><?php esc_html_e( 'DigitalOcean Backup Label', 'mainwp' ); ?></th>
1616 + <th scope="col" ><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1617 + <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1618 + <th scope="col" class="no-sort collapsing"></th>
1619 + <th scope="col" class="no-sort collapsing"></th>
1620 + </tr>
1621 + </tfoot>
1622 + </table>
1623 + <?php } ?>
1593 1624
1594 - // Send Payload & create backup.
1595 - $api_response = (array) self::call_cloudways_api( 'POST', '/app/manage/takeBackup', $accessToken, $data );
1625 + </div>
1626 + <script type="text/javascript">
1627 + let responsive = true;
1628 + if ( jQuery( window ).width() > 1140 ) {
1629 + responsive = false;
1630 + }
1631 + jQuery( document ).ready( function() {
1596 1632
1597 - $success = true;
1633 + jQuery( '.mainwp-api-backup-table' ).DataTable( {
1634 + "stateSave": true,
1635 + "stateDuration": 0,
1636 + "colReorder" : {columns:":not(.check-column):not(:last-child)"},
1637 + "responsive": responsive,
1638 + "scrollX": false,
1639 + "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
1640 + "columnDefs": [ { "targets": 'no-sort', "orderable": false } ],
1641 + "order": [ [ 1, "asc" ] ],
1642 + "language": { "emptyTable": "No backups found." },
1643 + "drawCallback": function( settings ) {
1644 + setTimeout(() => {
1645 + jQuery('.mainwp-api-backup-table .ui.checkbox').checkbox();
1646 + jQuery('.mainwp-api-backup-table .ui.dropdown').dropdown();
1647 + mainwp_datatable_fix_menu_overflow('.mainwp-api-backup-table', -55, 10 );
1648 + }, 1000);
1649 + }
1650 + } ).on( 'columns-reordered', function () {
1651 + setTimeout(() => {
1652 + jQuery( '.mainwp-api-backup-table .ui.dropdown' ).dropdown();
1653 + jQuery( '.mainwp-api-backup-table .ui.checkbox' ).checkbox();
1654 + mainwp_datatable_fix_menu_overflow('.mainwp-api-backup-table', -55, 10 );
1655 + mainwp_table_check_columns_init(); // ajax: to fix checkbox all.
1656 + }, 1000);
1657 + });
1658 + } );
1659 + </script>
1660 + <?php
1661 + } // END if.
1662 + }
1598 1663
1599 - if ( true !== $api_response['status'] ) {
1600 - $success = false;
1601 - } else {
1602 - // Save current backup operation.
1603 - $backup_operation = (array) self::call_cloudways_api( 'GET', '/operation/' . $api_response['operation_id'], $accessToken );
1604 - $backup_operation = wp_json_encode( $backup_operation['operation'] );
1605 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_backup_operation', $backup_operation );
1664 + /**
1665 + * Fetch Cloudways oAuth Access Token.
1666 + *
1667 + * Fetch the Cloudways oAuth access token from the given API credentials.
1668 + *
1669 + * @return mixed Return Cloudways Access Token.
1670 + */
1671 + public static function get_saved_v2_access_token() {
1672 + if ( null === static::$access_token ) {
1673 + static::$access_token = self::get_cloudways_access_token();
1674 + }
1675 + return static::$access_token;
1676 + }
1677 + /**
1678 + * Fetch Cloudways oAuth Access Token.
1679 + *
1680 + * Fetch the Cloudways oAuth access token from the given API credentials.
1681 + *
1682 + * @return mixed Return Cloudways Access Token.
1683 + */
1684 + public static function is_access_token_v2() {
1685 + return ! empty( self::get_saved_v2_access_token() );
1686 + }
1606 1687
1607 - // Save Timestamp.
1608 - $local_time = current_datetime();
1609 - $current_time = $local_time->getTimestamp() + $local_time->getOffset();
1610 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_last_backup', $current_time );
1611 - // Poll operations endpoint for backup status.
1612 - // self::cloudways_action_poll_backup_operation( $website_id );.
1613 - }
1688 + /*********************************************************************************
1689 + * Cloudways API Methods.
1690 + **********************************************************************************/
1614 1691
1615 - if ( $ret_val ) {
1616 - return $api_response;
1617 - }
1692 + /**
1693 + * Call Cloudways API, Authenticate & perform given method.
1694 + *
1695 + * Use this function to contact CW API
1696 + * We use OAuth, an open standard for authorization. Here are the steps involved:
1697 + * 1. Get your API Key from here: https://platform.cloudways.com/api
1698 + * 2. Enter in your account email address and API Key below.
1699 + *
1700 + * @param string $method GET|POST|PUT|DELETE.
1701 + * @param string $url relative URL for the call.
1702 + * @param array $post Optional post data for the call.
1703 + * @return object|false Output from CW API.
1704 + */
1705 + public static function call_cloudways_api_v2( $method, $url, $post = array() ) {
1618 1706
1619 - if ( ! $success ) {
1620 - wp_die( 'false' );
1621 - } else {
1622 - // Return success.
1623 - wp_send_json( 'true' );
1624 - // Poll operations endpoint for backup status.
1625 - // self::cloudways_action_poll_backup_operation( $website_id );.
1626 - }
1627 - }
1707 + $access_token = self::get_saved_v2_access_token();
1628 1708
1629 - /**
1630 - * Cloudways: action poll backup operation.
1631 - *
1632 - * Poll the Cloudways operations endpoint for backup status.
1633 - *
1634 - * @param int $website_id Website ID.
1635 - *
1636 - * @return void
1637 - */
1638 - public static function cloudways_action_poll_backup_operation( $website_id ) {
1709 + $ch = curl_init();
1639 1710
1640 - global $wp;
1711 + curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, $method );
1712 + curl_setopt( $ch, CURLOPT_URL, self::CLOUDWAYS_API_URL . $url );
1713 + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
1641 1714
1642 - // Grab needed site options from WP_MAINWP_WP_OPTIONS table.
1643 - $site_options = Api_Backups_Helper::get_website_options(
1644 - $website_id,
1645 - array(
1646 - 'mainwp_3rd_party_cloudways_backup_operation',
1647 - )
1648 - );
1715 + curl_setopt(
1716 + $ch,
1717 + CURLOPT_HTTPHEADER,
1718 + array(
1719 + 'Authorization: Bearer ' . $access_token,
1720 + 'Accept: application/json',
1721 + )
1722 + );
1649 1723
1650 - // Current backup operation.
1651 - $backup_operation = isset( $site_options['mainwp_3rd_party_cloudways_backup_operation'] ) ? $site_options['mainwp_3rd_party_cloudways_backup_operation'] : null;
1652 - $operation_id = json_decode( $backup_operation, true )['id'];
1724 + // Set Post Parameters.
1725 + $encoded = '';
1726 + if ( count( $post ) ) {
1727 + foreach ( $post as $name => $value ) {
1728 + $encoded .= rawurlencode( $name ) . '=' . rawurlencode( $value ) . '&';
1729 + }
1653 1730
1654 - // Grab Cloudways access token.
1655 - $accessToken = self::fetch_cloudways_access_token();
1731 + $encoded = substr( $encoded, 0, strlen( $encoded ) - 1 );
1656 1732
1657 - // Send Payload & list backups. https://api.cloudways.com/api/v1/operation/{id}.
1658 - $operation_polling = self::call_cloudways_api( 'GET', '/operation/' . $operation_id, $accessToken );
1659 - $backup_polling_response = $operation_polling->operation;
1733 + curl_setopt( $ch, CURLOPT_POSTFIELDS, $encoded );
1734 + curl_setopt( $ch, CURLOPT_POST, 1 );
1735 + }
1660 1736
1661 - // If backup has not been completed yet, sleep for 30 seconds and check again.
1662 - // If backup has been completed, save the backup operation results.
1663 - if ( true !== $backup_polling_response->is_completed ) {
1664 - sleep( 30 );
1665 - self::cloudways_action_poll_backup_operation( $website_id );
1666 - } else {
1667 - // Save current backup operation.
1668 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_backup_operation', wp_json_encode( $backup_polling_response ) );
1737 + $output = curl_exec( $ch );
1738 + $httpcode = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE );
1669 1739
1670 - // Refresh the page.
1671 - wp_safe_redirect( get_permalink( home_url( $wp->request ) ) );
1672 - }
1673 - // Return success.
1674 - wp_send_json( 'true' );
1675 - }
1740 + curl_close( $ch );
1676 1741
1677 - /**
1678 - * Cloudways: action refresh available backups.
1679 - *
1680 - * Save backups to DB for the selected Cloudways server.
1681 - *
1682 - * @return void
1683 - */
1684 - public static function cloudways_action_refresh_available_backups() {
1742 + if ( 200 !== $httpcode ) {
1743 + return false;
1744 + }
1685 1745
1686 - Api_Backups_Helper::security_nonce( 'cloudways_action_refresh_available_backups' );
1746 + return json_decode( $output );
1747 + }
1687 1748
1688 - // Grab website_id & backup_api name from Ajax post.
1689 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
1690 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
1691 - } else {
1692 - // Grab $_GET['data'] from url if not Ajax call.
1693 - $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
1694 - }
1749 + /**
1750 + * Call Cloudways API, Authenticate & perform given method.
1751 + *
1752 + * Use this function to contact CW API
1753 + * We use OAuth, an open standard for authorization. Here are the steps involved:
1754 + * 1. Get your API Key from here: https://platform.cloudways.com/api
1755 + * 2. Enter in your account email address and API Key below.
1756 + *
1757 + * @param string $method GET|POST|PUT|DELETE.
1758 + * @param string $url relative URL for the call.
1759 + * @param string $accessToken Access token generated using OAuth Call.
1760 + * @param array $post Optional post data for the call.
1761 + * @return object|false Output from CW API.
1762 + */
1763 + public static function call_cloudways_api( $method, $url, $accessToken, $post = array() ) {
1764 + $baseURL = 'https://api.cloudways.com/api/v1';
1695 1765
1696 - // Grab Cloudways access token.
1697 - $accessToken = self::fetch_cloudways_access_token();
1766 + $ch = curl_init();
1767 + curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, $method );
1768 + curl_setopt( $ch, CURLOPT_URL, $baseURL . $url );
1769 + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
1698 1770
1699 - // Grab needed site options from WP_MAINWP_WP_OPTIONS table.
1700 - $site_options = Api_Backups_Helper::get_website_options(
1701 - $website_id,
1702 - array(
1703 - 'mainwp_3rd_party_instance_id',
1704 - 'mainwp_3rd_party_app_id',
1705 - )
1706 - );
1707 - $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
1708 - $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
1771 + // Set Authorization Header.
1772 + if ( $accessToken ) {
1773 + curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Authorization: Bearer ' . $accessToken ) );
1774 + }
1709 1775
1710 - // Grab Backup operation from API.
1711 - $backup_operation = self::call_cloudways_api( 'GET', '/app/manage/backup?server_id=' . $server_id . '&app_id=' . $app_id, $accessToken );
1712 - $operation_id = $backup_operation->operation_id;
1776 + // Set Post Parameters.
1777 + $encoded = '';
1778 + if ( count( $post ) ) {
1779 + foreach ( $post as $name => $value ) {
1780 + $encoded .= rawurlencode( $name ) . '=' . rawurlencode( $value ) . '&';
1781 + }
1782 + $encoded = substr( $encoded, 0, strlen( $encoded ) - 1 );
1713 1783
1714 - sleep( 3 ); // REQUIRED! Wait 3 seconds for cURL connection to be closed before opening a new one.
1784 + curl_setopt( $ch, CURLOPT_POSTFIELDS, $encoded );
1785 + curl_setopt( $ch, CURLOPT_POST, 1 );
1786 + }
1715 1787
1716 - // Send Payload & list backups. https://api.cloudways.com/api/v1/operation/{id}.
1717 - $operation_polling = self::call_cloudways_api( 'GET', '/operation/' . $operation_id, $accessToken );
1718 - $operation = $operation_polling->operation;
1788 + $output = curl_exec( $ch );
1719 1789
1720 - // Save backup operation.
1721 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_available_backups', $operation->parameters );
1790 + $httpcode = (string) curl_getinfo( $ch, CURLINFO_HTTP_CODE );
1722 1791
1723 - Api_Backups_Utility::save_lasttime_backup( $website_id, $operation->parameters, 'cloudways' );
1792 + curl_close( $ch );
1724 1793
1725 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
1726 - if ( 1 !== (int) $operation->is_completed ) {
1727 - wp_die( 'false' );
1728 - } else {
1729 - // Return success.
1730 - wp_send_json( 'true' );
1731 - }
1732 - }
1733 - }
1794 + if ( '200' !== $httpcode ) {
1795 + return false;
1796 + }
1734 1797
1735 - /**
1736 - * Cloudways: action restore backup.
1737 - *
1738 - * Restore a backup on the selected Cloudways server.
1739 - *
1740 - * @return void
1741 - */
1742 - public function cloudways_action_restore_backup() {
1798 + return json_decode( $output );
1799 + }
1743 1800
1744 - Api_Backups_Helper::security_nonce( 'cloudways_action_restore_backup' );
1801 + /**
1802 + * Fetch Cloudways oAuth Access Token.
1803 + *
1804 + * Fetch the Cloudways oAuth access token from the given API credentials.
1805 + *
1806 + * @return mixed Return Cloudways Access Token.
1807 + */
1808 + public static function fetch_cloudways_access_token() {
1809 + $account_email = get_option( 'mainwp_cloudways_api_account_email' );
1810 + $api_key = static::get_cloudways_api_key();
1745 1811
1746 - // Grab website_id & backup_date name from Ajax post.
1747 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
1748 - $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
1812 + // Fetch Access Token.
1813 + $tokenResponse = static::call_cloudways_api(
1814 + 'POST',
1815 + '/oauth/access_token',
1816 + null,
1817 + array(
1818 + 'email' => $account_email,
1819 + 'api_key' => $api_key,
1820 + )
1821 + );
1822 + if ( empty( $tokenResponse ) ) {
1823 + return '';
1824 + }
1825 + return $tokenResponse->access_token;
1826 + }
1749 1827
1750 - // Grab needed site options from WP_MAINWP_WP_OPTIONS table.
1751 - $site_options = Api_Backups_Helper::get_website_options(
1752 - $website_id,
1753 - array(
1754 - 'mainwp_3rd_party_instance_id',
1755 - 'mainwp_3rd_party_app_id',
1756 - )
1757 - );
1758 - $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
1759 - $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
1828 + /**
1829 + * Fetch all available servers.
1830 + *
1831 + * @return mixed Returns available list of servers.
1832 + */
1833 + public static function fetch_cloudways_server_list() { //phpcs:ignore -- NOSONAR - complex.
1760 1834
1761 - // Payload to send to Cloudways API.
1762 - $data = array(
1763 - 'server_id' => $server_id,
1764 - 'app_id' => $app_id,
1765 - 'time' => $backup_date,
1766 - 'type' => 'complete',
1767 - );
1835 + if ( static::is_access_token_v2() ) {
1836 + $serverList = (array) static::call_cloudways_api_v2( 'GET', '/server' );
1837 + } else {
1838 + // Grab access token.
1839 + $accessToken = static::fetch_cloudways_access_token();
1768 1840
1769 - // Grab Cloudways access token.
1770 - $accessToken = self::fetch_cloudways_access_token();
1841 + // Fetch Server List.
1842 + $serverList = (array) static::call_cloudways_api( 'GET', '/server', $accessToken );
1843 + }
1771 1844
1772 - // Send Payload & create backup.
1773 - $api_response = self::call_cloudways_api( 'POST', '/app/manage/restore', $accessToken, $data );
1845 + if ( ! array_key_exists( 'servers', $serverList ) ) {
1846 + return;
1847 + }
1848 + // Return the server list.
1849 + return $serverList['servers'];
1850 + }
1774 1851
1775 - // Handle API response.
1776 - if ( 1 !== (int) $api_response->status ) {
1777 - wp_die( 'false' );
1778 - } else {
1779 - wp_send_json( 'true' );
1780 - }
1781 - }
1782 1852
1783 - /**
1784 - * Cloudways: action delete backup.
1785 - *
1786 - * Delete a backup on the selected Cloudways server.
1787 - *
1788 - * @return void
1789 - */
1790 - public function cloudways_action_delete_backup() {
1853 + /**
1854 + * Ajax.
1855 + * Save the server & app ID to that Child Site's options table.
1856 + *
1857 + * Compare connected Child Sites against connected Cloudways account.
1858 + * Automatically check for Child Sites domain name in server list & save.
1859 + * that app's Server ID & App ID to that Child Site's options table.
1860 + */
1861 + public function ajax_cloudways_action_update_ids() {
1862 + Api_Backups_Helper::security_nonce( 'cloudways_action_update_ids' );
1863 + static::cloudways_action_update_ids();
1864 + }
1791 1865
1792 - Api_Backups_Helper::security_nonce( 'cloudways_action_delete_backup' );
1866 + /**
1867 + * Save the server & app ID to that Child Site's options table.
1868 + *
1869 + * Compare connected Child Sites against connected Cloudways account.
1870 + * Automatically check for Child Sites domain name in server list & save.
1871 + * that app's Server ID & App ID to that Child Site's options table.
1872 + */
1873 + public static function cloudways_action_update_ids() {
1874 + // Fetch Child Site domains.
1875 + $child_sites = array();
1876 + $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
1793 1877
1794 - // Grab website_id from Ajax post.
1795 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
1878 + foreach ( $websites as $website ) {
1879 + $child_sites[ $website['id'] ] = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', urldecode( $website['url'] ) ) );
1880 + }
1796 1881
1797 - // Grab this from websites.
1798 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_app_id' ) );
1799 - $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
1800 - $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
1882 + // Fetch Cloudways Server List.
1883 + $server_list = static::fetch_cloudways_server_list();
1801 1884
1802 - $data = array(
1803 - 'server_id' => $server_id,
1804 - 'app_id' => $app_id,
1805 - );
1885 + /**
1886 + * Search $server_list for Child Site app ID & server ID.
1887 + *
1888 + * Loop through each Server/App & check if app cname / fqdn name matches any Child Site domain name.
1889 + * if so, save the server & app ID to that Child Site's options table.
1890 + */
1891 + if ( ! is_array( $server_list ) ) {
1892 + return;
1893 + }
1894 + foreach ( $server_list as $server ) {
1895 + foreach ( $server->apps as $app ) {
1896 + if ( in_array( $app->cname, $child_sites ) ) {
1897 + $found_child_site_id = array_search( $app->cname, $child_sites );
1898 + // Update Child Site options table.
1899 + Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_app_id', $app->id );
1900 + Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_instance_id', $app->server_id );
1901 + Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_api', 'Cloudways' );
1902 + } elseif ( in_array( $app->app_fqdn, $child_sites ) ) { // Check if app fqdn name matches any Child Site domain name, if so, save the server & app ID to that Child Site's options table.
1903 + $found_child_site_id = array_search( $app->app_fqdn, $child_sites );
1904 + // Update Child Site options table.
1905 + Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_app_id', $app->id );
1906 + Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_instance_id', $app->server_id );
1907 + Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_api', 'Cloudways' );
1908 + }
1909 + }
1910 + }
1911 + }
1806 1912
1807 - // Grab Cloudways access token.
1808 - $accessToken = self::fetch_cloudways_access_token();
1809 1913
1810 - // Send Payload & create backup.
1811 - $api_response = self::call_cloudways_api( 'DELETE', '/app/manage/backup', $accessToken, $data );
1914 + /**
1915 + * Cloudways: action backup.
1916 + *
1917 + * Perform a backup on the selected Cloudways server.
1918 + *
1919 + * @return void
1920 + */
1921 + public function ajax_cloudways_action_individual_backup() {
1922 + Api_Backups_Helper::security_nonce( 'cloudways_action_individual_backup' );
1923 + static::cloudways_action_backup();
1924 + }
1812 1925
1813 - if ( 1 !== (int) $api_response->status ) {
1814 - wp_die( 'false' );
1815 - } else {
1816 - wp_send_json( 'true' );
1817 - }
1818 - }
1926 + /**
1927 + * Cloudways: action backup.
1928 + *
1929 + * Perform a backup on the selected Cloudways server.
1930 + *
1931 + * @return void
1932 + */
1933 + public function ajax_cloudways_action_backup() {
1934 + Api_Backups_Helper::security_nonce( 'cloudways_action_backup' );
1935 + static::cloudways_action_create_backup();
1936 + }
1819 1937
1820 - /*********************************************************************************
1821 - * Vultr API Methods.
1822 - **********************************************************************************/
1938 + /**
1939 + * Cloudways: action backup.
1940 + *
1941 + * Perform a backup on the selected Cloudways server.
1942 + *
1943 + * @param int $website_id Website ID.
1944 + * @param bool $ret_val Return output or not.
1945 + *
1946 + * @return mixed
1947 + */
1948 + public static function cloudways_action_create_backup( $website_id = '', $ret_val = false ) {
1823 1949
1824 - /**
1825 - * Call Vultr API, Authenticate & perform given method.
1826 - *
1827 - * Use this function to contact Vultr API
1828 - * We use OAuth, an open standard for authorization. Here are the steps involved:
1829 - * 1. Get your API Key from here: https://platform.cloudways.com/api
1830 - * 2. Enter in your account email address and API Key below.
1831 - *
1832 - * @param string $method GET|POST|PUT|DELETE.
1833 - * @param string $url relative URL for the call.
1834 - * @param string $accessToken Access token generated using OAuth Call.
1835 - * @param string $data Json encoded array - Optional post data for the call.
1836 - * @param bool $die_error die when error.
1837 - *
1838 - * @return array Response from Vultr API.
1839 - */
1840 - public static function call_vultr_api( $method, $url, $accessToken, $data = null, $die_error = true ) {
1950 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : $website_id; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
1841 1951
1842 - $Baseurl = 'https://api.vultr.com/v2';
1952 + // Grab this from websites.
1953 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_app_id' ) );
1954 + $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
1955 + $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
1843 1956
1844 - $curl = curl_init( $Baseurl . $url );
1845 - curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, $method );
1846 - curl_setopt( $curl, CURLOPT_URL, $Baseurl . $url );
1847 - curl_setopt( $curl, CURLOPT_POST, true );
1848 - curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
1957 + $data = array(
1958 + 'server_id' => $server_id,
1959 + 'app_id' => $app_id,
1960 + );
1849 1961
1850 - $headers = array(
1851 - "Authorization: Bearer $accessToken",
1852 - 'Content-Type: application/json',
1853 - );
1854 - curl_setopt( $curl, CURLOPT_HTTPHEADER, $headers );
1855 - curl_setopt( $curl, CURLOPT_POSTFIELDS, $data );
1962 + $accessToken = '';
1856 1963
1857 - // for debug only!
1858 - curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, false );
1859 - curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false );
1964 + if ( static::is_access_token_v2() ) {
1965 + $api_response = (array) static::call_cloudways_api_v2( 'POST', '/app/manage/takeBackup', $data );
1966 + } else {
1860 1967
1861 - $resp = curl_exec( $curl );
1968 + // Grab Cloudways access token.
1969 + $accessToken = static::fetch_cloudways_access_token();
1862 1970
1863 - $response = array();
1864 - // Basic Error reporting. ( should wrap in try catch MainWP Exceptions call during code refactoring ).
1865 - $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
1866 - if ( ( '201' !== $httpCode ) && ( '200' !== $httpCode ) && ( '202' !== $httpCode ) && ( '204' !== $httpCode ) ) {
1867 - $decode_resp = json_decode( $resp );
1868 - $error = $decode_resp->error;
1869 - if ( $die_error ) { // die when error.
1870 - if ( isset( $_POST['bulk_backups'] ) && ! empty( $_POST['bulk_backups'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing
1871 - wp_send_json( array( 'error' => 'Code: ' . esc_html( $httpCode ) . ' - ' . esc_html( $error ) ) ); // to fix for backup selected sites (bulk).
1872 - } else {
1873 - die( 'Code: ' . esc_html( $httpCode ) . ' - ' . esc_html( $error ) );
1874 - }
1875 - } else {
1876 - $response['response'] = $decode_resp;
1877 - $response['status'] = false;
1878 - }
1879 - } else {
1880 - $response['response'] = json_decode( $resp );
1881 - $response['status'] = true;
1971 + // Send Payload & create backup.
1972 + $api_response = (array) static::call_cloudways_api( 'POST', '/app/manage/takeBackup', $accessToken, $data );
1973 + }
1882 1974
1883 - }
1884 - curl_close( $curl );
1885 - // Return Response.
1886 - return $response;
1887 - }
1975 + $success = true;
1888 1976
1977 + if ( true !== $api_response['status'] ) {
1978 + $success = false;
1979 + } else {
1980 + if ( static::is_access_token_v2() ) {
1981 + // Save current backup operation.
1982 + $backup_operation = (array) static::call_cloudways_api_v2( 'GET', static::OPERATION . $api_response['operation_id'] );
1983 + } else {
1984 + // Save current backup operation.
1985 + $backup_operation = (array) static::call_cloudways_api( 'GET', static::OPERATION . $api_response['operation_id'], $accessToken );
1986 + }
1889 1987
1988 + $backup_operation = wp_json_encode( $backup_operation['operation'] );
1989 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_backup_operation', $backup_operation );
1890 1990
1891 - /**
1892 - * Ajax.
1893 - * Vultr: action create snapshot.
1894 - *
1895 - * Create a snapshot on the selected Vultr server.
1896 - *
1897 - * This function is also called before any update. During this time a backup will be.
1898 - * Created but no updates will be made this time around. A new update will need to be manually triggered.
1899 - *
1900 - * @return void
1901 - */
1902 - public function ajax_vultr_action_individual_create_snapshot() {
1903 - Api_Backups_Helper::security_nonce( 'vultr_action_individual_create_snapshot' );
1904 - self::vultr_action_create_snapshot();
1905 - }
1991 + // Save Timestamp.
1992 + $local_time = current_datetime();
1993 + $current_time = $local_time->getTimestamp() + $local_time->getOffset();
1994 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_last_backup', $current_time );
1995 + // Poll operations endpoint for backup status.
1996 + // static::cloudways_action_poll_backup_operation( $website_id );.
1997 + }
1906 1998
1907 - /**
1908 - * Ajax.
1909 - * Vultr: action create snapshot.
1910 - *
1911 - * Create a snapshot on the selected Vultr server.
1912 - *
1913 - * This function is also called before any update. During this time a backup will be.
1914 - * Created but no updates will be made this time around. A new update will need to be manually triggered.
1915 - *
1916 - * @return void
1917 - */
1918 - public function ajax_vultr_action_create_snapshot() {
1919 - Api_Backups_Helper::security_nonce( 'vultr_action_create_snapshot' );
1920 - self::vultr_action_create_snapshot();
1921 - }
1999 + if ( $ret_val ) {
2000 + return $api_response;
2001 + }
1922 2002
1923 - /**
1924 - * Method get_vultr_api_key().
1925 - */
1926 - public static function get_vultr_api_key() {
1927 - return Api_Backups_Utility::get_instance()->get_api_key( 'vultr' );
1928 - }
2003 + if ( ! $success ) {
2004 + wp_die( 'false' );
2005 + } else {
2006 + // Return success.
2007 + wp_send_json( 'true' );
2008 + // Poll operations endpoint for backup status.
2009 + // static::cloudways_action_poll_backup_operation( $website_id );.
2010 + }
2011 + }
1929 2012
1930 - /**
1931 - * Method get_gridpane_api_key().
1932 - */
1933 - public static function get_gridpane_api_key() {
1934 - return Api_Backups_Utility::get_instance()->get_api_key( 'gridpane' );
1935 - }
2013 + /**
2014 + * Cloudways: action poll backup operation.
2015 + *
2016 + * Poll the Cloudways operations endpoint for backup status.
2017 + *
2018 + * @param int $website_id Website ID.
2019 + *
2020 + * @return void
2021 + */
2022 + public static function cloudways_action_poll_backup_operation( $website_id ) {
1936 2023
1937 - /**
1938 - * Method get_linode_api_key().
1939 - */
1940 - public static function get_linode_api_key() {
1941 - return Api_Backups_Utility::get_instance()->get_api_key( 'linode' );
1942 - }
2024 + global $wp;
1943 2025
1944 - /**
1945 - * Method get_digitalocean_api_key().
1946 - */
1947 - public static function get_digitalocean_api_key() {
1948 - return Api_Backups_Utility::get_instance()->get_api_key( 'digitalocean' );
1949 - }
2026 + // Grab needed site options from WP_MAINWP_WP_OPTIONS table.
2027 + $site_options = Api_Backups_Helper::get_website_options(
2028 + $website_id,
2029 + array(
2030 + 'mainwp_3rd_party_cloudways_backup_operation',
2031 + )
2032 + );
1950 2033
1951 - /**
1952 - * Method get_cloudways_api_key().
1953 - */
1954 - public static function get_cloudways_api_key() {
1955 - return Api_Backups_Utility::get_instance()->get_api_key( 'cloudways' );
1956 - }
2034 + // Current backup operation.
2035 + $backup_operation = isset( $site_options['mainwp_3rd_party_cloudways_backup_operation'] ) ? $site_options['mainwp_3rd_party_cloudways_backup_operation'] : null;
2036 + $operation_id = json_decode( $backup_operation, true )['id'];
1957 2037
1958 - /**
1959 - * Method get_cpanel_account_password().
1960 - */
1961 - public static function get_cpanel_account_password() {
1962 - return Api_Backups_Utility::get_instance()->get_api_key( 'cpanel' );
1963 - }
2038 + if ( static::is_access_token_v2() ) {
2039 + // Send Payload & list backups. https://api.cloudways.com/api/v1/operation/{id}.
2040 + $operation_polling = static::call_cloudways_api_v2( 'GET', static::OPERATION . $operation_id );
2041 + } else {
1964 2042
1965 - /**
1966 - * Method get_plesk_api_key().
1967 - */
1968 - public static function get_plesk_api_key() {
1969 - return Api_Backups_Utility::get_instance()->get_api_key( 'plesk' );
1970 - }
2043 + // Grab Cloudways access token.
2044 + $accessToken = static::fetch_cloudways_access_token();
1971 2045
1972 - /**
1973 - * Vultr: action create snapshot.
1974 - *
1975 - * Create a snapshot on the selected Vultr server.
1976 - *
1977 - * This function is also called before any update. During this time a backup will be
1978 - * Created but no updates will be made this time around. A new update will need to be manually triggered.
1979 - *
1980 - * @param int $website_id Website ID.
1981 - * @param string $backup_api Backup api.
1982 - * @param bool $ret_val Return output or not.
1983 - *
1984 - * @return mixed
1985 - */
1986 - public static function vultr_action_create_snapshot( $website_id = '', $backup_api = '', $ret_val = false ) {
2046 + // Send Payload & list backups. https://api.cloudways.com/api/v1/operation/{id}.
2047 + $operation_polling = static::call_cloudways_api( 'GET', static::OPERATION . $operation_id, $accessToken );
2048 + }
2049 + $backup_polling_response = $operation_polling->operation;
1987 2050
1988 - // Grab $_POST data if set else use args.
1989 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : intval( $website_id ); //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
1990 - $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
2051 + // If backup has not been completed yet, sleep for 30 seconds and check again.
2052 + // If backup has been completed, save the backup operation results.
2053 + if ( true !== $backup_polling_response->is_completed ) {
2054 + sleep( 30 );
2055 + static::cloudways_action_poll_backup_operation( $website_id );
2056 + } else {
2057 + // Save current backup operation.
2058 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_backup_operation', wp_json_encode( $backup_polling_response ) );
1991 2059
1992 - // Grab Site options.
1993 - $website = Api_Backups_Helper::get_website_by_id( $website_id );
2060 + // Refresh the page.
2061 + wp_safe_redirect( get_permalink( home_url( $wp->request ) ) );
2062 + }
2063 + // Return success.
2064 + wp_send_json( 'true' );
2065 + }
1994 2066
1995 - // Grab this from websites ( Static atm ).
1996 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_vultr_snapshot_list' ) );
1997 - $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
1998 - $snapshot_list = isset( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) ? $site_options['mainwp_3rd_party_vultr_snapshot_list'] : null;
2067 + /**
2068 + * Cloudways: action refresh available backups.
2069 + *
2070 + * Save backups to DB for the selected Cloudways server.
2071 + *
2072 + * @return void
2073 + */
2074 + public static function cloudways_action_refresh_available_backups() {
1999 2075
2000 - // Grab Vultr Access token.
2001 - $accessToken = self::get_vultr_api_key();
2076 + Api_Backups_Helper::security_nonce( 'cloudways_action_refresh_available_backups' );
2002 2077
2003 - // Remove http://, www., and slash(/) from the URL.
2004 - $url = ! empty( $website['url'] ) ? rawurlencode( $website['url'] ) : '';
2005 - $clean_url = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', urldecode( $url ) ) );
2078 + // Grab website_id & backup_api name from Ajax post.
2079 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2080 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2081 + } else {
2082 + // Grab $_GET['data'] from url if not Ajax call.
2083 + $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2084 + }
2006 2085
2007 - // Build payload data.
2008 - $snapshot_data = array(
2009 - 'instance_id' => $instance_id,
2010 - 'description' => 'MainWP API Backups -' . $clean_url,
2011 - );
2012 - $snapshot_data = wp_json_encode( $snapshot_data );
2013 2086
2014 - // Send Payload & create backup.
2015 - $snapshot_response = self::call_vultr_api( 'POST', '/snapshots', $accessToken, $snapshot_data );
2016 - $snapshot_id = $snapshot_response['response']->snapshot->id;
2087 + // Grab needed site options from WP_MAINWP_WP_OPTIONS table.
2088 + $site_options = Api_Backups_Helper::get_website_options(
2089 + $website_id,
2090 + array(
2091 + 'mainwp_3rd_party_instance_id',
2092 + 'mainwp_3rd_party_app_id',
2093 + )
2094 + );
2095 + $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2096 + $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
2017 2097
2018 - $snapshot_list = json_decode( $snapshot_list );
2019 - $snapshot_list[] = $snapshot_id;
2020 - $snapshot_list = wp_json_encode( $snapshot_list );
2098 + if ( static::is_access_token_v2() ) {
2099 + // Grab Backup operation from API.
2100 + $backup_operation = static::call_cloudways_api_v2( 'GET', '/app/manage/backup?server_id=' . $server_id . '&app_id=' . $app_id );
2101 + } else {
2102 + // Grab Cloudways access token.
2103 + $accessToken = static::fetch_cloudways_access_token();
2104 + // Grab Backup operation from API.
2105 + $backup_operation = static::call_cloudways_api( 'GET', '/app/manage/backup?server_id=' . $server_id . '&app_id=' . $app_id, $accessToken );
2106 + }
2021 2107
2022 - $success = true;
2023 - // Store Last Backup timestamp.
2024 - if ( empty( $snapshot_response ) ) {
2025 - $success = false;
2026 - } else {
2027 - $local_time = current_datetime();
2028 - $current_time = $local_time->getTimestamp() + $local_time->getOffset();
2029 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_' . $backup_api . '_last_backup', $current_time );
2030 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_vultr_snapshot_list', $snapshot_list );
2031 - }
2108 + $operation_id = $backup_operation->operation_id;
2032 2109
2033 - if ( $ret_val ) {
2034 - return $snapshot_response;
2035 - }
2110 + sleep( 3 ); // REQUIRED! Wait 3 seconds for cURL connection to be closed before opening a new one.
2036 2111
2037 - if ( $success ) {
2038 - // Return Response.
2039 - if ( ! empty( $_POST['website_id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2040 - wp_send_json( 'true' ); // Equivalent to die() - but for ajax.
2041 - } else {
2042 - return true;
2043 - }
2044 - } elseif ( ! empty( $_POST['website_id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2045 - $error = new WP_Error( '400', __( 'There was an issue with creating your backup.', 'mainwp' ) );
2046 - wp_send_json_error( $error );
2047 - } else {
2048 - return false;
2049 - }
2050 - }
2112 + if ( static::is_access_token_v2() ) {
2113 + $operation_polling = static::call_cloudways_api_v2( 'GET', static::OPERATION . $operation_id );
2114 + } else {
2115 + // Send Payload & list backups. https://api.cloudways.com/api/v1/operation/{id}.
2116 + $operation_polling = static::call_cloudways_api( 'GET', static::OPERATION . $operation_id, $accessToken );
2117 + }
2051 2118
2052 - /**
2053 - * Vultr: action refresh available backups.
2054 - *
2055 - * Save backups to DB for the selected Vultr server.
2056 - *
2057 - * @return void
2058 - */
2059 - public function vultr_action_refresh_available_backups() {
2060 - Api_Backups_Helper::security_nonce( 'vultr_action_refresh_available_backups' );
2119 + $operation = $operation_polling->operation;
2061 2120
2062 - // Grab website_id & backup_api name from Ajax post.
2063 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2064 - // Grab $_POST data.
2065 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2066 - } else {
2067 - // Grab $_GET data from url if not Ajax call.
2068 - $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2069 - }
2121 + // Save backup operation.
2122 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_available_backups', $operation->parameters );
2070 2123
2071 - // Grab this from websites ( Static atm ).
2072 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_vultr_snapshot_list' ) );
2073 - $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2074 - $snapshot_list = isset( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) ? json_decode( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) : null;
2124 + Api_Backups_Utility::save_lasttime_backup( $website_id, $operation->parameters, 'cloudways' );
2075 2125
2076 - // Grab Vultr Access token.
2077 - $accessToken = self::get_vultr_api_key();
2126 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2127 + if ( 1 !== (int) $operation->is_completed ) {
2128 + wp_die( 'false' );
2129 + } else {
2130 + // Return success.
2131 + wp_send_json( 'true' );
2132 + }
2133 + }
2134 + }
2078 2135
2079 - $success = false;
2080 - $die_error = false;
2136 + /**
2137 + * Cloudways: action restore backup.
2138 + *
2139 + * Restore a backup on the selected Cloudways server.
2140 + *
2141 + * @return void
2142 + */
2143 + public function cloudways_action_restore_backup() {
2081 2144
2082 - // Build available backups array.
2083 - $available_backups = array();
2084 - foreach ( $snapshot_list as $snapshot ) {
2085 - $api_response = self::call_vultr_api( 'GET', '/snapshots/' . $snapshot, $accessToken, null, $die_error );
2086 - $snapshot = $api_response['response'];
2087 - $available_backups['snapshots'] = $snapshot;
2088 - if ( is_array( $api_response ) && ! empty( $api_response['status'] ) ) {
2089 - $success = true;
2090 - }
2091 - }
2092 - $automatic_backups = self::call_vultr_api( 'GET', '/backups?instance_id=' . $instance_id, $accessToken, null, $die_error );
2093 - $automatic_backups = $automatic_backups['response']->backups;
2094 - $available_backups['backups'] = $automatic_backups;
2095 - $available_backups = wp_json_encode( $available_backups );
2145 + Api_Backups_Helper::security_nonce( 'cloudways_action_restore_backup' );
2096 2146
2097 - if ( ! $success && ! empty( $automatic_backups['status'] ) ) {
2098 - $success = true;
2099 - }
2147 + // Grab website_id & backup_date name from Ajax post.
2148 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2149 + $backup_date = isset( $_POST['backup_date'] ) ? wp_unslash( $_POST['backup_date'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2100 2150
2101 - // Grab Site options then update Child Site options.
2102 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_vultr_available_backups', $available_backups, $die_error );
2151 + // Grab needed site options from WP_MAINWP_WP_OPTIONS table.
2152 + $site_options = Api_Backups_Helper::get_website_options(
2153 + $website_id,
2154 + array(
2155 + 'mainwp_3rd_party_instance_id',
2156 + 'mainwp_3rd_party_app_id',
2157 + )
2158 + );
2159 + $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2160 + $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
2103 2161
2104 - if ( $success ) {
2105 - Api_Backups_Utility::save_lasttime_backup( $website_id, $available_backups, 'vultr' );
2106 - }
2162 + // Payload to send to Cloudways API.
2163 + $data = array(
2164 + 'server_id' => $server_id,
2165 + 'app_id' => $app_id,
2166 + 'time' => $backup_date,
2167 + 'type' => 'complete',
2168 + );
2107 2169
2108 - // Return AJAX.
2109 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2110 - // Store Available backups.
2111 - if ( $success ) {
2112 - wp_send_json( 'true' );
2113 - } else {
2114 - wp_send_json_error( $api_response );
2115 - }
2116 - }
2117 - }
2170 + if ( static::is_access_token_v2() ) {
2171 + $api_response = static::call_cloudways_api_v2( 'POST', '/app/manage/restore', $data );
2172 + } else {
2173 + // Grab Cloudways access token.
2174 + $accessToken = static::fetch_cloudways_access_token();
2118 2175
2119 - /**
2120 - * Vultr: action restore backup.
2121 - *
2122 - * Restore backup on the selected Vultr server.
2123 - *
2124 - * @return void
2125 - */
2126 - public function ajax_vultr_action_restore_backup() {
2127 - Api_Backups_Helper::security_nonce( 'vultr_action_restore_backup' );
2128 - self::vultr_action_restore_backup();
2129 - }
2176 + // Send Payload & create backup.
2177 + $api_response = static::call_cloudways_api( 'POST', '/app/manage/restore', $accessToken, $data );
2178 + }
2130 2179
2131 - /**
2132 - * Vultr: action restore backup.
2133 - *
2134 - * Restore backup on the selected Vultr server.
2135 - *
2136 - * @return void
2137 - */
2138 - public function vultr_action_restore_backup() {
2139 - // Grab $_POST data.
2140 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2141 - $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
2180 + // Handle API response.
2181 + if ( 1 !== (int) $api_response->status ) {
2182 + wp_die( 'false' );
2183 + } else {
2184 + wp_send_json( 'true' );
2185 + }
2186 + }
2142 2187
2143 - // Grab backup info from websites.
2144 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2145 - $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2188 + /**
2189 + * Cloudways: action delete backup.
2190 + *
2191 + * Delete a backup on the selected Cloudways server.
2192 + *
2193 + * @return void
2194 + */
2195 + public function cloudways_action_delete_backup() {
2146 2196
2147 - // Grab Access token.
2148 - $accessToken = self::get_vultr_api_key();
2149 - // Set which Backup to restore to.
2150 - $backup_data = array(
2151 - 'snapshot_id' => $snapshot_id,
2152 - );
2153 - $backup_data = wp_json_encode( $backup_data );
2197 + Api_Backups_Helper::security_nonce( 'cloudways_action_delete_backup' );
2154 2198
2155 - // Send Payload & list backups. backups/restore/1038'.
2156 - $api_response = (object) self::call_vultr_api( 'POST', '/instances/' . $instance_id . '/restore', $accessToken, $backup_data );
2199 + // Grab website_id from Ajax post.
2200 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2157 2201
2158 - // Return AJAX.
2159 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2160 - if ( 1 !== (int) $api_response->status ) {
2161 - wp_send_json_error( $api_response );
2162 - } else {
2163 - wp_send_json( 'true' );
2164 - }
2165 - }
2166 - }
2202 + // Grab this from websites.
2203 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_app_id' ) );
2204 + $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2205 + $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
2167 2206
2168 - /**
2169 - * Vultr: action delete backup.
2170 - *
2171 - * Delete a backup on the selected Vultr server.
2172 - *
2173 - * @return void
2174 - */
2175 - public function vultr_action_delete_backup() {
2207 + $data = array(
2208 + 'server_id' => $server_id,
2209 + 'app_id' => $app_id,
2210 + );
2176 2211
2177 - Api_Backups_Helper::security_nonce( 'vultr_action_delete_backup' );
2212 + // Grab Cloudways access token.
2213 + $accessToken = static::fetch_cloudways_access_token();
2178 2214
2179 - // Grab $_GET['data'] from url if not Ajax call.
2180 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2181 - $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
2182 - // $snapshot_id acecab84-7404-4193-bc9f-88e29956362f;
2215 + // Send Payload & create backup.
2216 + $api_response = static::call_cloudways_api( 'DELETE', '/app/manage/backup', $accessToken, $data );
2183 2217
2184 - // Grab Vultr Access token.
2185 - $accessToken = self::get_vultr_api_key();
2218 + if ( 1 !== (int) $api_response->status ) {
2219 + wp_die( 'false' );
2220 + } else {
2221 + wp_send_json( 'true' );
2222 + }
2223 + }
2186 2224
2187 - // Send Payload & delete backup.
2188 - $api_response = (object) self::call_vultr_api( 'DELETE', '/snapshots/' . $snapshot_id, $accessToken );
2225 + /*********************************************************************************
2226 + * Vultr API Methods.
2227 + **********************************************************************************/
2189 2228
2190 - // Remove backup from snapshot list.
2191 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_vultr_snapshot_list' ) );
2192 - $snapshot_list = isset( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) ? json_decode( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) : null;
2229 + /**
2230 + * Call Vultr API, Authenticate & perform given method.
2231 + *
2232 + * Use this function to contact Vultr API
2233 + * We use OAuth, an open standard for authorization. Here are the steps involved:
2234 + * 1. Get your API Key from here: https://platform.cloudways.com/api
2235 + * 2. Enter in your account email address and API Key below.
2236 + *
2237 + * @param string $method GET|POST|PUT|DELETE.
2238 + * @param string $url relative URL for the call.
2239 + * @param string $accessToken Access token generated using OAuth Call.
2240 + * @param string $data Json encoded array - Optional post data for the call.
2241 + * @param bool $die_error die when error.
2242 + *
2243 + * @return array Response from Vultr API.
2244 + */
2245 + public static function call_vultr_api( $method, $url, $accessToken, $data = null, $die_error = true ) {
2193 2246
2194 - $key = array_search( $snapshot_id, $snapshot_list );
2195 - if ( false !== $key ) {
2196 - unset( $snapshot_list[ $key ] );
2197 - }
2198 - $snapshot_list = wp_json_encode( $snapshot_list );
2247 + $baseurl = 'https://api.vultr.com/v2';
2199 2248
2200 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_vultr_snapshot_list', $snapshot_list );
2201 - // die.
2202 - // Return AJAX.
2203 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2204 - // Return Ajax response.
2205 - if ( 1 !== (int) $api_response->status ) {
2206 - wp_send_json_error( 'false' );
2249 + $curl = curl_init( $baseurl . $url );
2250 + curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, $method );
2251 + curl_setopt( $curl, CURLOPT_URL, $baseurl . $url );
2252 + curl_setopt( $curl, CURLOPT_POST, true );
2253 + curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
2207 2254
2208 - } else {
2209 - wp_send_json( 'true' );
2210 - }
2211 - }
2212 - }
2255 + $headers = array(
2256 + "Authorization: Bearer $accessToken",
2257 + 'Content-Type: application/json',
2258 + );
2259 + curl_setopt( $curl, CURLOPT_HTTPHEADER, $headers );
2260 + curl_setopt( $curl, CURLOPT_POSTFIELDS, $data );
2213 2261
2214 - /*********************************************************************************
2215 - * GridPane API Methods.
2216 - **********************************************************************************/
2262 + $ssl_verifyhost = ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 === (int) get_option( 'mainwp_sslVerifyCertificate' ) );
2217 2263
2218 - /**
2219 - * Call GridPane API, Authenticate & perform given method.
2220 - *
2221 - * Use this function to contact GridPane API
2222 - * We use OAuth, an open standard for authorization. Here are the steps involved:
2223 - * 1. Get your API Key from here: https://platform.cloudways.com/api
2224 - * 2. Enter in your account email address and API Key below.
2225 - *
2226 - * @param string $method GET|POST|PUT|DELETE.
2227 - * @param string $url relative URL for the call.
2228 - * @param string $accessToken Access token generated using OAuth Call.
2229 - * @param mixed $backup_data Json encoded array - Optional post data for the call.
2230 - *
2231 - * @return string Output from GridPane API.
2232 - */
2233 - public static function call_gridpane_api( $method, $url, $accessToken, $backup_data = array() ) {
2264 + if ( $ssl_verifyhost ) {
2265 + curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, 2 );
2266 + curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, true );
2267 + } else {
2268 + // for debug only!
2269 + curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, false ); // NOSONAR.
2270 + curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false ); // NOSONAR.
2271 + }
2234 2272
2235 - $Baseurl = 'https://my.gridpane.com/oauth/api/v1';
2236 - $curl = curl_init();
2237 - curl_setopt_array(
2238 - $curl,
2239 - array(
2240 - CURLOPT_URL => $Baseurl . $url,
2241 - CURLOPT_RETURNTRANSFER => true,
2242 - CURLOPT_ENCODING => '',
2243 - CURLOPT_MAXREDIRS => 10,
2244 - CURLOPT_TIMEOUT => 0,
2245 - CURLOPT_FOLLOWLOCATION => true,
2246 - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
2247 - CURLOPT_CUSTOMREQUEST => $method,
2248 - CURLOPT_POSTFIELDS => $backup_data,
2249 - CURLOPT_HTTPHEADER => array(
2250 - "Authorization: Bearer $accessToken",
2251 - 'Content-Type: application/json',
2252 - ),
2253 - )
2254 - );
2255 - $response = curl_exec( $curl );
2256 - curl_close( $curl );
2257 - return $response;
2258 - }
2273 + $resp = curl_exec( $curl );
2259 2274
2260 - /**
2261 - * Get GridPane Site List.
2262 - *
2263 - * Request for all sites for current user token.
2264 - *
2265 - * @param int $sites_count sites count.
2266 - * @return object|bool Return Sites Object.
2267 - */
2268 - public static function gridpane_get_sites_list( $sites_count ) {
2275 + $response = array();
2276 + // Basic Error reporting. ( should wrap in try catch MainWP Exceptions call during code refactoring ).
2277 + $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
2278 + if ( ( '201' !== $httpCode ) && ( '200' !== $httpCode ) && ( '202' !== $httpCode ) && ( '204' !== $httpCode ) ) {
2279 + $decode_resp = json_decode( $resp );
2280 + $error = $decode_resp->error;
2281 + if ( $die_error ) { // die when error.
2282 + if ( isset( $_POST['bulk_backups'] ) && ! empty( $_POST['bulk_backups'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing
2283 + wp_send_json( array( 'error' => 'Code: ' . esc_html( $httpCode ) . ' - ' . esc_html( $error ) ) ); // to fix for backup selected sites (bulk).
2284 + } else {
2285 + die( 'Code: ' . esc_html( $httpCode ) . ' - ' . esc_html( $error ) );
2286 + }
2287 + } else {
2288 + $response['response'] = $decode_resp;
2289 + $response['status'] = false;
2290 + }
2291 + } else {
2292 + $response['response'] = json_decode( $resp );
2293 + $response['status'] = true;
2269 2294
2270 - // Grab Vultr Access token.
2271 - $accessToken = self::get_gridpane_api_key();
2295 + }
2296 + curl_close( $curl );
2297 + // Return Response.
2298 + return $response;
2299 + }
2272 2300
2273 - // Grab Sites List.
2274 - $grid_response = (array) self::call_gridpane_api( 'GET', '/site?per_page=' . $sites_count, $accessToken );
2275 - $grid_response_decoded = json_decode( $grid_response[0] );
2276 - if ( is_object( $grid_response_decoded ) && property_exists( $grid_response_decoded, 'data' ) ) {
2277 - return $grid_response_decoded->data;
2278 - }
2279 - return false;
2280 - }
2281 2301
2282 - /**
2283 - * Ajax.
2284 - * Assign Server:Apps to Child Sites options table.
2285 - *
2286 - * Compare connected Child Sites against connected GridPane account.
2287 - * Automatically check for Child Sites domain name in server list & save
2288 - * that app's Server ID & App ID to that Child Site's options table.
2289 - *
2290 - * @return void True|False Return True on success & False on failure
2291 - */
2292 - public function ajax_gridpane_action_update_ids() {
2293 - Api_Backups_Helper::security_nonce( 'gridpane_action_update_ids' );
2294 - self::gridpane_action_update_ids();
2295 - }
2296 2302
2297 - /**
2298 - * Assign Server:Apps to Child Sites options table.
2299 - *
2300 - * Compare connected Child Sites against connected GridPane account.
2301 - * Automatically check for Child Sites domain name in server list & save
2302 - * that app's Server ID & App ID to that Child Site's options table.
2303 - *
2304 - * @return void True|False Return True on success & False on failure
2305 - */
2306 - public static function gridpane_action_update_ids() {
2303 + /**
2304 + * Ajax.
2305 + * Vultr: action create snapshot.
2306 + *
2307 + * Create a snapshot on the selected Vultr server.
2308 + *
2309 + * This function is also called before any update. During this time a backup will be.
2310 + * Created but no updates will be made this time around. A new update will need to be manually triggered.
2311 + *
2312 + * @return void
2313 + */
2314 + public function ajax_vultr_action_individual_create_snapshot() {
2315 + Api_Backups_Helper::security_nonce( 'vultr_action_individual_create_snapshot' );
2316 + static::vultr_action_create_snapshot();
2317 + }
2307 2318
2308 - // Grab site count & pass to gridpane_get_sites_list() for pagination.
2309 - $sites_count = Api_Backups_Utility::get_instance()->count_child_sites();
2319 + /**
2320 + * Ajax.
2321 + * Vultr: action create snapshot.
2322 + *
2323 + * Create a snapshot on the selected Vultr server.
2324 + *
2325 + * This function is also called before any update. During this time a backup will be.
2326 + * Created but no updates will be made this time around. A new update will need to be manually triggered.
2327 + *
2328 + * @return void
2329 + */
2330 + public function ajax_vultr_action_create_snapshot() {
2331 + Api_Backups_Helper::security_nonce( 'vultr_action_create_snapshot' );
2332 + static::vultr_action_create_snapshot();
2333 + }
2310 2334
2311 - // Get child_sites list.
2312 - $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
2335 + /**
2336 + * Method get_vultr_api_key().
2337 + */
2338 + public static function get_vultr_api_key() {
2339 + return Api_Backups_Utility::get_instance()->get_api_key( 'vultr' );
2340 + }
2313 2341
2314 - // Compare Child Sites domain against connected GridPane account Server / Apps List.
2315 - while ( $websites && ( $website = Api_Backups_Helper::fetch_object( $websites ) ) ) {
2316 - // Remove http://, www., and slash(/) from the URL.
2317 - $url = rawurlencode( $website->url );
2318 - $strip_protocall = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', urldecode( $url ) ) );
2319 - $clean_url = preg_replace( '/^www\./', '', $strip_protocall );
2342 + /**
2343 + * Method get_gridpane_api_key().
2344 + */
2345 + public static function get_gridpane_api_key() {
2346 + return Api_Backups_Utility::get_instance()->get_api_key( 'gridpane' );
2347 + }
2320 2348
2321 - // Get Sites list.
2322 - $sites_list = self::gridpane_get_sites_list( $sites_count );
2349 + /**
2350 + * Method get_linode_api_key().
2351 + */
2352 + public static function get_linode_api_key() {
2353 + return Api_Backups_Utility::get_instance()->get_api_key( 'linode' );
2354 + }
2323 2355
2324 - // Check for Child Site IP @ each instance. Add to Child Site Options Table.
2325 - if ( is_array( $sites_list ) ) {
2326 - foreach ( $sites_list as $site ) {
2327 - if ( $site->url === $clean_url ) {
2328 - // Grab Site options then update Child Site options.
2329 - Api_Backups_Helper::update_website_option( $website->id, 'mainwp_3rd_party_instance_id', $site->id );
2330 - Api_Backups_Helper::update_website_option( $website->id, 'mainwp_3rd_party_api', 'GridPane' );
2331 - }
2332 - }
2333 - }
2334 - }
2356 + /**
2357 + * Method get_digitalocean_api_key().
2358 + */
2359 + public static function get_digitalocean_api_key() {
2360 + return Api_Backups_Utility::get_instance()->get_api_key( 'digitalocean' );
2361 + }
2335 2362
2336 - Api_Backups_Helper::free_result( $websites );
2337 - }
2363 + /**
2364 + * Method get_cloudways_api_key().
2365 + */
2366 + public static function get_cloudways_api_key() {
2367 + return Api_Backups_Utility::get_instance()->get_api_key( 'cloudways' );
2368 + }
2338 2369
2339 - /**
2340 - * Ajax.
2341 - * GridPane: action create backup.
2342 - *
2343 - * Create a backup on the selected GridPane server.
2344 - *
2345 - * @return void
2346 - */
2347 - public function ajax_gridpane_action_individual_create_backup() {
2348 - Api_Backups_Helper::security_nonce( 'gridpane_action_individual_create_backup' );
2349 - self::gridpane_action_create_backup();
2350 - }
2370 + /**
2371 + * Method get_cloudways_access_token().
2372 + */
2373 + public static function get_cloudways_access_token() {
2374 + return Api_Backups_Utility::get_instance()->get_api_key( 'cloudways', '', 'access_token' );
2375 + }
2351 2376
2352 - /**
2353 - * Ajax.
2354 - * GridPane: action create backup.
2355 - *
2356 - * Create a backup on the selected GridPane server.
2357 - *
2358 - * @return void
2359 - */
2360 - public function ajax_gridpane_action_create_backup() {
2361 - Api_Backups_Helper::security_nonce( 'gridpane_action_create_backup' );
2362 - self::gridpane_action_create_backup();
2363 - }
2364 2377
2365 - /**
2366 - * GridPane: action create backup.
2367 - *
2368 - * @param int $website_id Website ID.
2369 - * @param bool $ret_val Return output or not.
2370 - *
2371 - * @return mixed
2372 - */
2373 - public static function gridpane_action_create_backup( $website_id = '', $ret_val = false ) {
2378 + /**
2379 + * Method get_cpanel_account_password().
2380 + */
2381 + public static function get_cpanel_account_password() {
2382 + return Api_Backups_Utility::get_instance()->get_api_key( 'cpanel' );
2383 + }
2374 2384
2375 - // Grab $_POST data.
2376 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : intval( $website_id ); //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2385 + /**
2386 + * Method get_plesk_api_key().
2387 + */
2388 + public static function get_plesk_api_key() {
2389 + return Api_Backups_Utility::get_instance()->get_api_key( 'plesk' );
2390 + }
2377 2391
2378 - // Grab this from websites.
2379 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2380 - $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2392 + /**
2393 + * Method get_kinsta_api_key().
2394 + */
2395 + public static function get_kinsta_api_key() {
2396 + return Api_Backups_Utility::get_instance()->get_api_key( 'kinsta' );
2397 + }
2381 2398
2382 - // Grab Gridpane Access token.
2383 - $accessToken = self::get_gridpane_api_key();
2399 + /**
2400 + * Vultr: action create snapshot.
2401 + *
2402 + * Create a snapshot on the selected Vultr server.
2403 + *
2404 + * This function is also called before any update. During this time a backup will be
2405 + * created but no updates will be made this time around. A new update will need to be manually triggered.
2406 + *
2407 + * @param int $website_id website id.
2408 + * @param string $backup_api backup api.
2409 + *
2410 + * @return mixed result.
2411 + */
2412 + public static function vultr_action_create_snapshot( $website_id = '', $backup_api = '' ) {
2384 2413
2385 - // Set Backup `type` & `tag`.
2386 - $backup_data = array(
2387 - 'type' => 'local',
2388 - 'tag' => 'MainWP-API-Backups',
2389 - );
2390 - $backup_data = wp_json_encode( $backup_data );
2414 + // Grab $_POST data if set else use args.
2415 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : intval( $website_id ); //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2416 + $backup_api = isset( $_POST['backup_api'] ) ? wp_unslash( $_POST['backup_api'] ) : $backup_api; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2391 2417
2392 - // Send Payload & create backup.
2393 - $backup_response = self::call_gridpane_api( 'POST', '/backups/' . $site_id, $accessToken, $backup_data );
2394 - $backup_status = json_decode( $backup_response );
2418 + // Grab Site options.
2419 + $website = Api_Backups_Helper::get_website_by_id( $website_id );
2395 2420
2396 - // DON'T REMOVE THIS LINE - for debugging.
2397 - // error_log(print_r($backup_response, true));.
2398 - $success = false;
2399 - $error = false;
2400 - // Store Last Backup timestamp.
2401 - if ( $backup_status && ! empty( $backup_status->success ) ) {
2402 - $success = true;
2403 - $local_time = current_datetime();
2404 - $current_time = $local_time->getTimestamp() + $local_time->getOffset();
2405 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_gridpane_last_backup', $current_time );
2406 - } else {
2407 - $error = new WP_Error( $backup_status->error->code, __( $backup_status->error->message, 'mainwp' ) );
2408 - }
2421 + // Grab this from websites ( Static atm ).
2422 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_vultr_snapshot_list' ) );
2423 + $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2424 + $snapshot_list = isset( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) ? $site_options['mainwp_3rd_party_vultr_snapshot_list'] : null;
2409 2425
2410 - if ( $ret_val ) {
2411 - return $backup_status;
2412 - }
2426 + // Grab Vultr Access token.
2427 + $accessToken = static::get_vultr_api_key();
2413 2428
2414 - if ( $success ) {
2415 - wp_send_json( 'true' );
2416 - } else {
2417 - if ( empty( $error ) ) {
2418 - $error = esc_html__( 'Undefined error. Please try again.', 'mainwp' );
2419 - }
2420 - wp_send_json_error( $error );
2421 - }
2422 - }
2429 + // Remove http://, www., and slash(/) from the URL.
2430 + $url = ! empty( $website['url'] ) ? rawurlencode( $website['url'] ) : '';
2431 + $clean_url = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', urldecode( $url ) ) );
2423 2432
2424 - /**
2425 - * GridPane: action refresh available backups.
2426 - *
2427 - * Save backups to DB for the selected GridPane server.
2428 - *
2429 - * @return void
2430 - */
2431 - public function gridpane_action_refresh_available_backups() {
2433 + // Build payload data.
2434 + $snapshot_data = array(
2435 + 'instance_id' => $instance_id,
2436 + 'description' => 'MainWP API Backups -' . $clean_url,
2437 + );
2438 + $snapshot_data = wp_json_encode( $snapshot_data );
2432 2439
2433 - Api_Backups_Helper::security_nonce( 'gridpane_action_refresh_available_backups' );
2440 + // Send Payload & create backup.
2441 + $snapshot_response = static::call_vultr_api( 'POST', '/snapshots', $accessToken, $snapshot_data );
2442 + $snapshot_id = $snapshot_response['response']->snapshot->id;
2434 2443
2435 - // Grab website_id & backup_api name from Ajax post.
2436 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2437 - // Grab $_POST data.
2438 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2439 - } else {
2440 - // Grab $_GET['data'] from url if not Ajax call.
2441 - $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2442 - }
2444 + $snapshot_list = json_decode( $snapshot_list );
2445 + $snapshot_list[] = $snapshot_id;
2446 + $snapshot_list = wp_json_encode( $snapshot_list );
2443 2447
2444 - // Grab IDs from websites.
2445 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2446 - $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2448 + $success = true;
2449 + // Store Last Backup timestamp.
2450 + if ( empty( $snapshot_response ) ) {
2451 + $success = false;
2452 + } else {
2453 + $local_time = current_datetime();
2454 + $current_time = $local_time->getTimestamp() + $local_time->getOffset();
2455 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_' . $backup_api . '_last_backup', $current_time );
2456 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_vultr_snapshot_list', $snapshot_list );
2457 + }
2447 2458
2448 - // Grab Gridpane Access token.
2449 - $accessToken = self::get_gridpane_api_key();
2459 + if ( $ret_val ) {
2460 + return $snapshot_response;
2461 + }
2450 2462
2451 - // Refresh backups.
2452 - self::call_gridpane_api( 'GET', '/backups/refresh/' . $site_id, $accessToken );
2463 + if ( $success ) {
2464 + // Return Response.
2465 + if ( ! empty( $_POST['website_id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2466 + wp_send_json( 'true' ); // Equivalent to die() - but for ajax.
2467 + } else {
2468 + return true;
2469 + }
2470 + } elseif ( ! empty( $_POST['website_id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2471 + $error = new WP_Error( '400', __( 'There was an issue with creating your backup.', 'mainwp' ) );
2472 + wp_send_json_error( $error );
2473 + } else {
2474 + return false;
2475 + }
2476 + }
2453 2477
2454 - // Send Payload & grab backup list.
2455 - $api_response = json_decode( self::call_gridpane_api( 'GET', '/backups/original/' . $site_id, $accessToken ) );
2478 + /**
2479 + * Vultr: action refresh available backups.
2480 + *
2481 + * Save backups to DB for the selected Vultr server.
2482 + *
2483 + * @return void
2484 + */
2485 + public function vultr_action_refresh_available_backups() { //phpcs:ignore -- NOSONAR - complex.
2486 + Api_Backups_Helper::security_nonce( 'vultr_action_refresh_available_backups' );
2456 2487
2457 - $available_backups = '';
2458 - if ( $api_response && ! empty( $api_response->backups ) && ! empty( $api_response->backups->local ) ) {
2459 - $available_backups = wp_json_encode( $api_response->backups->local );
2460 - }
2488 + // Grab website_id & backup_api name from Ajax post.
2489 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2490 + // Grab $_POST data.
2491 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2492 + } else {
2493 + // Grab $_GET data from url if not Ajax call.
2494 + $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2495 + }
2461 2496
2462 - // Update Child Site option with available backup list.
2463 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_gridpane_available_backups', $available_backups );
2497 + // Grab this from websites ( Static atm ).
2498 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_vultr_snapshot_list' ) );
2499 + $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2500 + $snapshot_list = isset( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) ? json_decode( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) : null;
2464 2501
2465 - Api_Backups_Utility::save_lasttime_backup( $website_id, $available_backups, 'gridpane' );
2502 + // Grab Vultr Access token.
2503 + $accessToken = static::get_vultr_api_key();
2466 2504
2467 - // Return AJAX.
2468 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2469 - if ( true !== $api_response->success ) {
2470 - wp_send_json_error( 'No Backups Found' );
2505 + $success = false;
2506 + $die_error = false;
2471 2507
2472 - } else {
2473 - wp_send_json( 'true' );
2474 - }
2475 - }
2476 - }
2508 + // Build available backups array.
2509 + $available_backups = array();
2510 + foreach ( $snapshot_list as $snapshot ) {
2511 + $api_response = static::call_vultr_api( 'GET', static::SNAPSHOTS . $snapshot, $accessToken, null, $die_error );
2512 + $snapshot = $api_response['response'];
2513 + $available_backups['snapshots'] = $snapshot;
2514 + if ( is_array( $api_response ) && ! empty( $api_response['status'] ) ) {
2515 + $success = true;
2516 + }
2517 + }
2518 + $automatic_backups = static::call_vultr_api( 'GET', '/backups?instance_id=' . $instance_id, $accessToken, null, $die_error );
2519 + $automatic_backups = $automatic_backups['response']->backups;
2520 + $available_backups['backups'] = $automatic_backups;
2521 + $available_backups = wp_json_encode( $available_backups );
2477 2522
2478 - /**
2479 - * GridPane: action restore backup.
2480 - *
2481 - * Restore selected backup for the selected GridPane server.
2482 - *
2483 - * @return void
2484 - */
2485 - public function gridpane_action_restore_backup() {
2523 + if ( ! $success && ! empty( $automatic_backups['status'] ) ) {
2524 + $success = true;
2525 + }
2486 2526
2487 - Api_Backups_Helper::security_nonce( 'gridpane_action_restore_backup' );
2527 + // Grab Site options then update Child Site options.
2528 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_vultr_available_backups', $available_backups, $die_error );
2488 2529
2489 - // Grab $_POST data.
2490 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2491 - $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
2492 - $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
2530 + if ( $success ) {
2531 + Api_Backups_Utility::save_lasttime_backup( $website_id, $available_backups, 'vultr' );
2532 + }
2493 2533
2494 - // Grab backup info from websites.
2495 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2496 - $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2534 + // Return AJAX.
2535 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2536 + // Store Available backups.
2537 + if ( $success ) {
2538 + wp_send_json( 'true' );
2539 + } else {
2540 + wp_send_json_error( $api_response );
2541 + }
2542 + }
2543 + }
2497 2544
2498 - // Grab Gridpane Access token.
2499 - $accessToken = self::get_gridpane_api_key();
2545 + /**
2546 + * Vultr: action restore backup.
2547 + *
2548 + * Restore backup on the selected Vultr server.
2549 + *
2550 + * @return void
2551 + */
2552 + public function ajax_vultr_action_restore_backup() {
2553 + Api_Backups_Helper::security_nonce( 'vultr_action_restore_backup' );
2554 + static::vultr_action_restore_backup();
2555 + }
2500 2556
2501 - // Set which Backup to restore to.
2502 - $backup_data = array(
2503 - 'backup_source' => 'local',
2504 - 'source_type' => 'original',
2505 - 'backup_type' => $backup_type,
2506 - 'backup' => $backup_name,
2507 - );
2508 - $backup_data = wp_json_encode( $backup_data );
2557 + /**
2558 + * Vultr: action restore backup.
2559 + *
2560 + * Restore backup on the selected Vultr server.
2561 + *
2562 + * @return void
2563 + */
2564 + public function vultr_action_restore_backup() {
2565 + // Grab $_POST data.
2566 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2567 + $snapshot_id = isset( $_POST['snapshot_id'] ) ? wp_unslash( $_POST['snapshot_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2509 2568
2510 - // Send Payload & list backups. backups/restore/1038'.
2511 - $api_response = json_decode( self::call_gridpane_api( 'POST', '/backups/restore/' . $site_id, $accessToken, $backup_data ) );
2569 + // Grab backup info from websites.
2570 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2571 + $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2512 2572
2513 - // Return AJAX.
2514 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2515 - if ( '1' !== (string) $api_response->success ) {
2516 - wp_send_json_error( 'false' );
2573 + // Grab Access token.
2574 + $accessToken = static::get_vultr_api_key();
2575 + // Set which Backup to restore to.
2576 + $backup_data = array(
2577 + 'snapshot_id' => $snapshot_id,
2578 + );
2579 + $backup_data = wp_json_encode( $backup_data );
2517 2580
2518 - }
2519 - wp_send_json( 'true' );
2520 - }
2521 - }
2581 + // Send Payload & list backups. backups/restore/1038'.
2582 + $api_response = (object) static::call_vultr_api( 'POST', static::INSTANCES . $instance_id . '/restore', $accessToken, $backup_data );
2522 2583
2523 - /**
2524 - * GridPane: action delete backup.
2525 - *
2526 - * Delete backup for the selected GridPane server.
2527 - *
2528 - * @return void
2529 - */
2530 - public function gridpane_action_delete_backup() {
2584 + // Return AJAX.
2585 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2586 + if ( 1 !== (int) $api_response->status ) {
2587 + wp_send_json_error( $api_response );
2588 + } else {
2589 + wp_send_json( 'true' );
2590 + }
2591 + }
2592 + }
2531 2593
2532 - Api_Backups_Helper::security_nonce( 'gridpane_action_delete_backup' );
2594 + /**
2595 + * Vultr: action delete backup.
2596 + *
2597 + * Delete a backup on the selected Vultr server.
2598 + *
2599 + * @return void
2600 + */
2601 + public function vultr_action_delete_backup() {
2533 2602
2534 - // Grab $_POST data.
2535 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2536 - $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
2537 - $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
2603 + Api_Backups_Helper::security_nonce( 'vultr_action_delete_backup' );
2538 2604
2539 - // Grab backup info from websites.
2540 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2541 - $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2605 + // Grab $_GET['data'] from url if not Ajax call.
2606 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2607 + $snapshot_id = isset( $_POST['snapshot_id'] ) ? wp_unslash( $_POST['snapshot_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2608 + // $snapshot_id acecab84-7404-4193-bc9f-88e29956362f;
2542 2609
2543 - // Grab Gridpane Access token.
2544 - $accessToken = self::get_gridpane_api_key();
2610 + // Grab Vultr Access token.
2611 + $accessToken = static::get_vultr_api_key();
2545 2612
2546 - // Set which Backup to restore to.
2547 - $backup_data = array(
2548 - 'backup_source' => 'local',
2549 - 'backup_type' => $backup_type,
2550 - 'backup' => $backup_name,
2551 - );
2552 - $backup_data = wp_json_encode( $backup_data );
2613 + // Send Payload & delete backup.
2614 + $api_response = (object) static::call_vultr_api( 'DELETE', static::SNAPSHOTS . $snapshot_id, $accessToken );
2553 2615
2554 - // Send Payload & delete backup.
2555 - $api_response = json_decode( self::call_gridpane_api( 'PUT', '/backups/purge/' . $site_id, $accessToken, $backup_data ) );
2616 + // Remove backup from snapshot list.
2617 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_vultr_snapshot_list' ) );
2618 + $snapshot_list = isset( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) ? json_decode( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) : null;
2556 2619
2557 - // Return AJAX.
2558 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2559 - if ( '1' !== (string) $api_response->success ) {
2560 - wp_send_json_error( 'false' );
2561 - }
2562 - wp_send_json( 'true' );
2563 - }
2564 - }
2620 + $key = array_search( $snapshot_id, $snapshot_list );
2621 + if ( false !== $key ) {
2622 + unset( $snapshot_list[ $key ] );
2623 + }
2624 + $snapshot_list = wp_json_encode( $snapshot_list );
2565 2625
2626 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_vultr_snapshot_list', $snapshot_list );
2627 + // die.
2628 + // Return AJAX.
2629 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2630 + // Return Ajax response.
2631 + if ( 1 !== (int) $api_response->status ) {
2632 + wp_send_json_error( 'false' );
2566 2633
2567 - /*********************************************************************************
2568 - * Linode API Methods.
2569 - **********************************************************************************/
2634 + } else {
2635 + wp_send_json( 'true' );
2636 + }
2637 + }
2638 + }
2570 2639
2571 - /**
2572 - * Call Linode API, Authenticate & perform given method.
2573 - *
2574 - * Use this function to contact Linode API
2575 - * We use OAuth, an open standard for authorization. Here are the steps involved:
2576 - * 1. Get your API Key from here: https://platform.cloudways.com/api
2577 - * 2. Enter in your account email address and API Key below.
2578 - *
2579 - * @param string $method GET|POST|PUT|DELETE.
2580 - * @param string $url relative URL for the call.
2581 - * @param string $accessToken Access token generated using OAuth Call.
2582 - * @param mixed $backup_data Json encoded array - Optional post data for the call.
2583 - * @return string Output from GridPane API.
2584 - */
2585 - public static function call_linode_api( $method, $url, $accessToken, $backup_data = array() ) {
2640 + /*********************************************************************************
2641 + * GridPane API Methods.
2642 + **********************************************************************************/
2586 2643
2587 - $Baseurl = 'https://api.linode.com/v4/linode';
2588 - $curl = curl_init();
2589 - curl_setopt_array(
2590 - $curl,
2591 - array(
2592 - CURLOPT_URL => $Baseurl . $url,
2593 - CURLOPT_RETURNTRANSFER => true,
2594 - CURLOPT_ENCODING => '',
2595 - CURLOPT_MAXREDIRS => 10,
2596 - CURLOPT_TIMEOUT => 0,
2597 - CURLOPT_FOLLOWLOCATION => true,
2598 - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
2599 - CURLOPT_CUSTOMREQUEST => $method,
2600 - CURLOPT_POSTFIELDS => $backup_data,
2601 - CURLOPT_HTTPHEADER => array(
2602 - "Authorization: Bearer $accessToken",
2603 - 'Content-Type: application/json',
2604 - ),
2605 - )
2606 - );
2644 + /**
2645 + * Call GridPane API, Authenticate & perform given method.
2646 + *
2647 + * Use this function to contact GridPane API
2648 + * We use OAuth, an open standard for authorization. Here are the steps involved:
2649 + * 1. Get your API Key from here: https://platform.cloudways.com/api
2650 + * 2. Enter in your account email address and API Key below.
2651 + *
2652 + * @param string $method GET|POST|PUT|DELETE.
2653 + * @param string $url relative URL for the call.
2654 + * @param string $accessToken Access token generated using OAuth Call.
2655 + * @param mixed $backup_data Json encoded array - Optional post data for the call.
2656 + *
2657 + * @return string Output from GridPane API.
2658 + */
2659 + public static function call_gridpane_api( $method, $url, $accessToken, $backup_data = array() ) {
2607 2660
2608 - $response = curl_exec( $curl );
2661 + $baseurl = 'https://my.gridpane.com/oauth/api/v1';
2662 + $curl = curl_init();
2663 + curl_setopt_array(
2664 + $curl,
2665 + array(
2666 + CURLOPT_URL => $baseurl . $url,
2667 + CURLOPT_RETURNTRANSFER => true,
2668 + CURLOPT_ENCODING => '',
2669 + CURLOPT_MAXREDIRS => 10,
2670 + CURLOPT_TIMEOUT => 0,
2671 + CURLOPT_FOLLOWLOCATION => true,
2672 + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
2673 + CURLOPT_CUSTOMREQUEST => $method,
2674 + CURLOPT_POSTFIELDS => $backup_data,
2675 + CURLOPT_HTTPHEADER => array(
2676 + "Authorization: Bearer $accessToken",
2677 + 'Content-Type: application/json',
2678 + ),
2679 + )
2680 + );
2681 + $response = curl_exec( $curl );
2682 + curl_close( $curl );
2683 + return $response;
2684 + }
2609 2685
2610 - curl_close( $curl );
2611 - return $response;
2612 - }
2686 + /**
2687 + * Get GridPane Site List.
2688 + *
2689 + * Request for all sites for current user token.
2690 + *
2691 + * @param int $sites_count sites count.
2692 + * @return object|bool Return Sites Object.
2693 + */
2694 + public static function gridpane_get_sites_list( $sites_count ) {
2613 2695
2614 - /**
2615 - * Linode: action create backup.
2616 - *
2617 - * Create backup for the selected Linode server.
2618 - *
2619 - * @return void
2620 - */
2621 - public function ajax_linode_action_individual_create_backup() {
2622 - Api_Backups_Helper::security_nonce( 'linode_action_individual_create_backup' );
2623 - self::linode_action_create_backup();
2624 - die();
2625 - }
2696 + // Grab Vultr Access token.
2697 + $accessToken = static::get_gridpane_api_key();
2626 2698
2627 - /**
2628 - * Linode: action create backup.
2629 - *
2630 - * Create backup for the selected Linode server.
2631 - *
2632 - * @return void
2633 - */
2634 - public function ajax_linode_action_create_backup() {
2635 - Api_Backups_Helper::security_nonce( 'linode_action_create_backup' );
2636 - self::linode_action_create_backup();
2637 - die();
2638 - }
2699 + // Grab Sites List.
2700 + $grid_response = (array) static::call_gridpane_api( 'GET', '/site?per_page=' . $sites_count, $accessToken );
2701 + Api_Backups_Utility::log_debug( 'GridPane API get sites :: [response=' . ( is_array( $grid_response ) ? print_r( $grid_response, true ) : 'INVALID' ). '] :: ' . $accessToken ); // phpcs:ignore -- NOSONAR - for debugging.
2702 + $grid_response_decoded = json_decode( $grid_response[0] );
2703 + if ( is_object( $grid_response_decoded ) && property_exists( $grid_response_decoded, 'data' ) ) {
2704 + return $grid_response_decoded->data;
2705 + }
2706 + return false;
2707 + }
2639 2708
2640 - /**
2641 - * Linode: action create backup.
2642 - *
2643 - * Create backup for the selected Linode server.
2644 - *
2645 - * @param int $website_id Website ID.
2646 - * @param bool $ret_val Return output or not.
2647 - *
2648 - * @return mixed
2649 - */
2650 - public static function linode_action_create_backup( $website_id = '', $ret_val = false ) {
2709 + /**
2710 + * Get GridPane Site List.
2711 + *
2712 + * Request for all sites for current user token.
2713 + *
2714 + * @return object|bool Return Sites Object.
2715 + */
2716 + public static function gridpane_get_domain_list() {
2651 2717
2652 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : $website_id; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2718 + // Grab Vultr Access token.
2719 + $accessToken = static::get_gridpane_api_key();
2653 2720
2654 - // Grab IDs from websites.
2655 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2656 - $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2721 + // Grab Sites List.
2722 + $grid_response = (array) static::call_gridpane_api( 'GET', '/domain', $accessToken );
2723 + $grid_response_decoded = json_decode( $grid_response[0] );
2724 + if ( is_object( $grid_response_decoded ) && property_exists( $grid_response_decoded, 'data' ) ) {
2725 + return $grid_response_decoded->data;
2726 + }
2727 + return false;
2728 + }
2657 2729
2658 - // Grab Linode Access token.
2659 - $accessToken = self::get_linode_api_key();
2730 + /**
2731 + * Ajax.
2732 + * Assign Server:Apps to Child Sites options table.
2733 + *
2734 + * Compare connected Child Sites against connected GridPane account.
2735 + * Automatically check for Child Sites domain name in server list & save
2736 + * that app's Server ID & App ID to that Child Site's options table.
2737 + *
2738 + * @return void True|False Return True on success & False on failure
2739 + */
2740 + public function ajax_gridpane_action_update_ids() {
2741 + Api_Backups_Helper::security_nonce( 'gridpane_action_update_ids' );
2742 + static::gridpane_action_update_ids();
2743 + }
2660 2744
2661 - // Send Payload & create backup.
2662 - $linode_response = (array) self::call_linode_api( 'POST', '/instances/' . $instance_id . '/backups', $accessToken );
2663 - $linode_response = json_decode( $linode_response[0] );
2745 + /**
2746 + * Assign Server:Apps to Child Sites options table.
2747 + *
2748 + * Compare connected Child Sites against connected GridPane account.
2749 + * Automatically check for Child Sites domain name in server list & save
2750 + * that app's Server ID & App ID to that Child Site's options table.
2751 + *
2752 + * @return void True|False Return True on success & False on failure
2753 + */
2754 + public static function gridpane_action_update_ids() { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR - complexity.
2664 2755
2665 - $success = true;
2756 + // Get child_sites list from MainWP.
2757 + $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
2666 2758
2667 - // Handle response.
2668 - if ( isset( $linode_response->errors ) ) {
2669 - $success = false;
2670 - } else {
2671 - $local_time = current_datetime();
2672 - $current_time = $local_time->getTimestamp() + $local_time->getOffset();
2673 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_linode_last_backup', $current_time );
2674 - }
2759 + // Build an array of websites by URL.
2760 + $websites_by_urls = array();
2761 + if ( $websites ) {
2762 + while ( $websites && ( $website = Api_Backups_Helper::fetch_object( $websites ) ) ) {
2763 + $clean_url = Api_Backups_Helper::clean_url( $website->url );
2764 + $websites_by_urls[ $clean_url ] = $website->id;
2765 + }
2766 + MainWP_DB::data_seek( $websites, 0 );
2767 + }
2675 2768
2676 - if ( $ret_val ) {
2677 - return $linode_response;
2678 - }
2769 + // Get GP Sites list.
2770 + $sites_list = static::gridpane_get_sites_list( 99999 ); // 99999 to pull all sites. High number at least for now.
2679 2771
2680 - // Handle response.
2681 - if ( isset( $linode_response->errors ) ) {
2682 - $error = new WP_Error( '400', __( $linode_response->errors['0']->reason, 'mainwp' ) );
2683 - // Return AJAX.
2684 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2685 - wp_send_json_error( $error );
2772 + $logs_updated_sites = array();
2686 2773
2687 - }
2688 - } elseif ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2689 - wp_send_json( 'true' ); // Return AJAX.
2690 - }
2691 - die();
2692 - }
2774 + // Loop through Child Sites.
2775 + while ( $websites && ( $website = Api_Backups_Helper::fetch_object( $websites ) ) ) {
2693 2776
2694 - /**
2695 - * Linode: action Refresh available backups.
2696 - *
2697 - * Save backups to DB for the selected Linode server.
2698 - *
2699 - * @return void
2700 - */
2701 - public function linode_action_refresh_available_backups() {
2702 - Api_Backups_Helper::security_nonce( 'linode_action_refresh_available_backups' );
2703 - // Grab website_id & backup_api name from Ajax post.
2704 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2705 - // Grab $_POST data.
2706 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2707 - } else {
2708 - // Grab $_GET['data'] from url if not Ajax call.
2709 - $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2710 - }
2777 + // Grab non-stagingChild Site ID.
2778 + $website_id = $website->id;
2711 2779
2712 - // Grab Child Site options.
2713 - // Grab IDs from websites.
2714 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2715 - $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2780 + // Remove http(s)://, www., and trailing slash(/) from the URL.
2781 + $clean_url = Api_Backups_Helper::clean_url( $website->url );
2716 2782
2717 - // Grab Vultr Access token.
2718 - $accessToken = self::get_linode_api_key();
2783 + /**
2784 + * Check if the URLs of Child Sites match with those of GridPane Sites.
2785 + * If they do, add the GridPane Site ID and the provider name 'GridPane'
2786 + * to the Child Site options table.
2787 + */
2788 + if ( is_array( $sites_list ) ) {
2789 + foreach ( $sites_list as $site ) {
2719 2790
2720 - // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/backups.
2721 - $api_response = (object) self::call_linode_api( 'GET', '/instances/' . $instance_id . '/backups', $accessToken );
2722 - $all_backups = $api_response->scalar;
2791 + // If the URL of the Child Site matches the URL of the GridPane Site.
2792 + if ( $site->url === $clean_url ) {
2723 2793
2724 - // Grab Site options then update Child Site options.
2725 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_linode_available_backups', $all_backups );
2794 + // GridPane Site found here....
2726 2795
2727 - Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'linode' );
2796 + // Grab GridPane Site ID.
2797 + $gp_site_id = $site->id;
2728 2798
2729 - // Return AJAX.
2730 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2731 - // Store Available backups.
2732 - if ( ! $all_backups ) {
2733 - wp_send_json_error( $api_response );
2734 - } else {
2735 - wp_send_json( 'true' );
2736 - }
2737 - }
2738 - }
2799 + // Update Production Child Site options.
2800 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_instance_id', $gp_site_id );
2801 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_api', 'GridPane' );
2802 + $logs_updated_sites[ $clean_url ] = $gp_site_id;
2803 + // Check if the site is a staging site.
2804 + if ( ! empty( $site->staging_site_built_at ) && isset( $websites_by_urls[ 'staging.' . $site->url ] ) ) {
2805 + $staging_child_site_id = $websites_by_urls[ 'staging.' . $site->url ];
2739 2806
2740 - /**
2741 - * Linode: action Restore backup.
2742 - *
2743 - * Restore backup for the selected Linode server.
2744 - *
2745 - * @return void
2746 - */
2747 - public function linode_action_restore_backup() {
2807 + $logs_updated_sites[ 'staging.' . $site->url ] = $gp_site_id + 1;
2748 2808
2749 - Api_Backups_Helper::security_nonce( 'linode_action_restore_backup' );
2809 + // Update Staging Child Site options.
2810 + Api_Backups_Helper::update_website_option( $staging_child_site_id, 'mainwp_3rd_party_instance_id', $gp_site_id + 1 );
2811 + Api_Backups_Helper::update_website_option( $staging_child_site_id, 'mainwp_3rd_party_api', 'GridPane' );
2812 + }
2813 + break;
2814 + }
2815 + }
2816 + }
2817 + }
2818 + Api_Backups_Utility::log_debug( 'Updated GridPane API Sites :: [total=' . count( $logs_updated_sites ) . '] :: [' . print_r( $logs_updated_sites, true ) . ']' ); // phpcs:ignore -- NOSONAR - for debugging.
2750 2819
2751 - // Grab $_POST data.
2752 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2753 - $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
2820 + $logs_sites_lists = array();
2821 + if ( is_array( $sites_list ) ) {
2822 + foreach ( $sites_list as $site ) {
2823 + $logs_sites_lists[ $site->url ] = $site->id;
2824 + }
2825 + }
2826 + Api_Backups_Utility::log_debug( 'GridPane Sites Lists:: [total=' . count( $logs_sites_lists ) . '] :: [' . print_r( $logs_sites_lists, true ) . ']' ); // phpcs:ignore -- NOSONAR - for debugging.
2754 2827
2755 - // Grab IDs from websites.
2756 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2757 - $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2828 + Api_Backups_Helper::free_result( $websites );
2829 + }
2758 2830
2759 - // Grab Linode Access token.
2760 - $accessToken = self::get_linode_api_key();
2831 + /**
2832 + * Ajax.
2833 + * GridPane: action create backup.
2834 + *
2835 + * Create a backup on the selected GridPane server.
2836 + *
2837 + * @return void
2838 + */
2839 + public function ajax_gridpane_action_individual_create_backup() {
2840 + Api_Backups_Helper::security_nonce( 'gridpane_action_individual_create_backup' );
2841 + static::gridpane_action_create_backup();
2842 + }
2761 2843
2762 - // Set which Backup to restore to.
2763 - $backup_data = array(
2764 - 'instance_id' => $instance_id,
2765 - 'overwrite' => true,
2766 - );
2767 - $backup_data = wp_json_encode( $backup_data );
2844 + /**
2845 + * Ajax.
2846 + * GridPane: action create backup.
2847 + *
2848 + * Create a backup on the selected GridPane server.
2849 + *
2850 + * @return void
2851 + */
2852 + public function ajax_gridpane_action_create_backup() {
2853 + Api_Backups_Helper::security_nonce( 'gridpane_action_create_backup' );
2854 + static::gridpane_action_create_backup();
2855 + }
2768 2856
2769 - // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/backups/{backupId}/restore.
2770 - $restore_response = (array) self::call_linode_api( 'POST', '/instances/' . $instance_id . '/backups/' . $backup_id . '/restore', $accessToken, $backup_data );
2771 - $restore_response = (array) json_decode( $restore_response['0'] );
2857 + /**
2858 + * GridPane: action create backup.
2859 + *
2860 + * @param int $website_id Website ID.
2861 + * @param bool $ret_val Return output or not.
2862 + *
2863 + * @return mixed
2864 + */
2865 + public static function gridpane_action_create_backup( $website_id = '', $ret_val = false ) {
2772 2866
2773 - sleep( 20 );
2774 - self::linode_action_linode_status( $website_id );
2775 - }
2867 + // Grab $_POST data.
2868 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : intval( $website_id ); //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2776 2869
2777 - /**
2778 - * Linode: action Linode status.
2779 - *
2780 - * Check linode status to know when to reboot server.
2781 - *
2782 - * @param int $website_id Child Site ID.
2783 - *
2784 - * @return void
2785 - */
2786 - public static function linode_action_linode_status( $website_id ) {
2870 + // Grab this from websites.
2871 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2872 + $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2787 2873
2788 - // Grab IDs from websites.
2789 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2790 - $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2874 + // Grab Gridpane Access token.
2875 + $accessToken = static::get_gridpane_api_key();
2791 2876
2792 - // Grab Linode Access token.
2793 - $accessToken = self::get_linode_api_key();
2877 + // Set Backup `type` & `tag`.
2878 + $backup_data = array(
2879 + 'type' => 'local',
2880 + 'tag' => 'MainWP-API-Backups',
2881 + );
2882 + $backup_data = wp_json_encode( $backup_data );
2794 2883
2795 - // Send Payload & grab instance status. https://api.linode.com/v4/linode/instances/{linodeId}.
2796 - $linode_instance_response = (array) self::call_linode_api( 'GET', '/instances/' . $instance_id, $accessToken );
2797 - $linode_instance_response = json_decode( $linode_instance_response['0'] );
2798 - $linode_instance_status = $linode_instance_response->status;
2884 + // Send Payload & create backup.
2885 + $backup_response = static::call_gridpane_api( 'POST', '/backups/' . $site_id, $accessToken, $backup_data );
2886 + $backup_status = json_decode( $backup_response );
2799 2887
2800 - // Check if linode status is 'offline'.
2801 - // Check linode status to know when to reboot server.
2802 - switch ( $linode_instance_status ) {
2803 - case 'running':
2804 - case 'restoring':
2805 - case 'Linode Busy.':
2806 - // Re-Check status.
2807 - sleep( 1 );
2808 - self::linode_action_linode_status( $website_id );
2809 - break;
2810 - case 'offline':
2811 - // Starting server.
2812 - self::linode_action_linode_start( $instance_id );
2813 - break;
2814 - }
2815 - }
2888 + $success = false;
2889 + $error = false;
2890 + // Store Last Backup timestamp.
2891 + if ( $backup_status && ! empty( $backup_status->success ) ) {
2892 + $success = true;
2893 + $local_time = current_datetime();
2894 + $current_time = $local_time->getTimestamp() + $local_time->getOffset();
2895 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_gridpane_last_backup', $current_time );
2896 + } else {
2897 + $error = new WP_Error( $backup_status->error->code, $backup_status->error->message );
2898 + }
2816 2899
2817 - /**
2818 - * Linode: action Linode start.
2819 - *
2820 - * @param int $instance_id Linode Instance ID.
2821 - *
2822 - * @return void
2823 - */
2824 - public static function linode_action_linode_start( $instance_id ) {
2825 - sleep( 10 );
2826 - // Grab Linode Access token.
2827 - $accessToken = self::get_linode_api_key();
2900 + if ( $ret_val ) {
2901 + return $backup_status;
2902 + }
2828 2903
2829 - // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/boot.
2830 - $linode_boot_response = (array) self::call_linode_api( 'POST', '/instances/' . $instance_id . '/boot', $accessToken );
2831 - $linode_boot_response = (array) json_decode( $linode_boot_response['0'] );
2904 + if ( $success ) {
2905 + wp_send_json( 'true' );
2906 + } else {
2907 + if ( empty( $error ) ) {
2908 + $error = esc_html__( 'Undefined error. Please try again.', 'mainwp' );
2909 + }
2910 + wp_send_json_error( $error );
2911 + }
2912 + }
2832 2913
2833 - wp_send_json( 'true' );
2834 - }
2914 + /**
2915 + * GridPane: action refresh available backups.
2916 + *
2917 + * Save backups to DB for the selected GridPane server.
2918 + *
2919 + * @return void
2920 + */
2921 + public function gridpane_action_refresh_available_backups() {
2835 2922
2836 - /**
2837 - * Linode: action cancel backups.
2838 - *
2839 - * Cancel all backups for a Linode Instance.
2840 - *
2841 - * @return void
2842 - */
2843 - public function linode_action_cancel_backups() {
2923 + Api_Backups_Helper::security_nonce( 'gridpane_action_refresh_available_backups' );
2844 2924
2845 - Api_Backups_Helper::security_nonce( 'linode_action_cancel_backups' );
2925 + // Grab website_id & backup_api name from Ajax post.
2926 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2927 + // Grab $_POST data.
2928 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2929 + } else {
2930 + // Grab $_GET['data'] from url if not Ajax call.
2931 + $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2932 + }
2846 2933
2847 - // Grab $_POST data.
2848 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2849 - $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
2934 + // Grab IDs from websites.
2935 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2936 + $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2850 2937
2851 - // Grab IDs from websites.
2852 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2853 - $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2938 + // Grab Gridpane Access token.
2939 + $accessToken = static::get_gridpane_api_key();
2854 2940
2855 - // Grab Vultr Access token.
2856 - $accessToken = self::get_linode_api_key();
2941 + // Refresh backups.
2942 + static::call_gridpane_api( 'GET', '/backups/refresh/' . $site_id, $accessToken );
2857 2943
2858 - // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/backups/cancel.
2859 - $api_response = (object) self::call_linode_api( 'POST', '/instances/' . $instance_id . '/backups/cancel', $accessToken );
2944 + // Send Payload & grab backup list.
2945 + $api_response = json_decode( static::call_gridpane_api( 'GET', '/backups/original/' . $site_id, $accessToken ) );
2860 2946
2861 - // Return AJAX.
2862 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2863 - // Store Available backups.
2864 - if ( ! $api_response ) {
2865 - wp_send_json_error( 'false' );
2947 + $available_backups = '';
2948 + if ( $api_response && ! empty( $api_response->backups ) && ! empty( $api_response->backups->local ) ) {
2949 + $available_backups = wp_json_encode( $api_response->backups->local );
2950 + }
2866 2951
2867 - } else {
2868 - $all_backups = array();
2869 - // Grab Site options then update Child Site options.
2870 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_linode_available_backups', $all_backups );
2871 - }
2872 - wp_send_json( 'true' );
2873 - }
2874 - }
2952 + // Update Child Site option with available backup list.
2953 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_gridpane_available_backups', $available_backups );
2875 2954
2876 - /*********************************************************************************
2877 - * DigitalOcean API Methods.
2878 - **********************************************************************************/
2955 + Api_Backups_Utility::save_lasttime_backup( $website_id, $available_backups, 'gridpane' );
2879 2956
2880 - /**
2881 - * Call DigitalOcean API, Authenticate & perform given method.
2882 - *
2883 - * @param string $method GET|POST|PUT|DELETE.
2884 - * @param string $url relative URL for the call.
2885 - * @param string $accessToken Access token generated using OAuth Call.
2886 - * @param mixed $backup_data Json encoded array - Optional post data for the call.
2887 - * @return array Output from DigitalOcean API.
2888 - */
2889 - public static function call_digitalocean_api( $method, $url, $accessToken, $backup_data = array() ) {
2957 + // Return AJAX.
2958 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2959 + if ( true !== $api_response->success ) {
2960 + wp_send_json_error( 'No Backups Found' );
2890 2961
2891 - $Baseurl = 'https://api.digitalocean.com/v2';
2962 + } else {
2963 + wp_send_json( 'true' );
2964 + }
2965 + }
2966 + }
2892 2967
2893 - $curl = curl_init();
2894 - curl_setopt_array(
2895 - $curl,
2896 - array(
2897 - CURLOPT_URL => $Baseurl . $url,
2898 - CURLOPT_RETURNTRANSFER => true,
2899 - CURLOPT_ENCODING => '',
2900 - CURLOPT_MAXREDIRS => 10,
2901 - CURLOPT_TIMEOUT => 0,
2902 - CURLOPT_FOLLOWLOCATION => true,
2903 - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
2904 - CURLOPT_CUSTOMREQUEST => $method,
2905 - CURLOPT_POSTFIELDS => $backup_data,
2906 - CURLOPT_HTTPHEADER => array(
2907 - "Authorization: Bearer $accessToken",
2908 - 'Content-Type: application/json',
2909 - ),
2910 - )
2911 - );
2968 + /**
2969 + * GridPane: action restore backup.
2970 + *
2971 + * Restore selected backup for the selected GridPane server.
2972 + *
2973 + * @return void
2974 + */
2975 + public function gridpane_action_restore_backup() {
2912 2976
2913 - $resp = curl_exec( $curl );
2977 + Api_Backups_Helper::security_nonce( 'gridpane_action_restore_backup' );
2914 2978
2915 - $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
2916 - $response['httpCode'] = $httpCode;
2917 - $response['response'] = $resp;
2918 - if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
2919 - $response['status'] = 'false';
2920 - } else {
2921 - $response['status'] = 'true';
2979 + // Grab $_POST data.
2980 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2981 + $backup_type = isset( $_POST['backup_type'] ) ? wp_unslash( $_POST['backup_type'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2982 + $backup_name = isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2922 2983
2923 - }
2924 - curl_close( $curl );
2925 - return $response;
2926 - }
2984 + // Grab backup info from websites.
2985 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2986 + $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2927 2987
2988 + // Grab Gridpane Access token.
2989 + $accessToken = static::get_gridpane_api_key();
2928 2990
2929 - /**
2930 - * DigitalOcean: Action create backup.
2931 - *
2932 - * Create a backup of the droplet.
2933 - *
2934 - * @return void
2935 - */
2936 - public function ajax_digitalocean_action_create_backup() {
2937 - Api_Backups_Helper::security_nonce( 'digitalocean_action_create_backup' );
2938 - self::digitalocean_action_create_backup();
2939 - }
2991 + // Set which Backup to restore to.
2992 + $backup_data = array(
2993 + 'backup_source' => 'local',
2994 + 'source_type' => 'original',
2995 + 'backup_type' => $backup_type,
2996 + 'backup' => $backup_name,
2997 + );
2998 + $backup_data = wp_json_encode( $backup_data );
2940 2999
2941 - /**
2942 - * DigitalOcean: Action create backup.
2943 - *
2944 - * Create a backup of the droplet.
2945 - *
2946 - * @return void
2947 - */
2948 - public function ajax_digitalocean_action_individual_create_backup() {
2949 - Api_Backups_Helper::security_nonce( 'digitalocean_action_individual_create_backup' );
2950 - self::digitalocean_action_create_backup();
2951 - }
3000 + // Send Payload & list backups. backups/restore/1038'.
3001 + $api_response = json_decode( static::call_gridpane_api( 'POST', '/backups/restore/' . $site_id, $accessToken, $backup_data ) );
2952 3002
2953 - /**
2954 - * DigitalOcean: Action create backup.
2955 - *
2956 - * Create a backup of the droplet.
2957 - *
2958 - * @param int $website_id Website ID.
2959 - * @param bool $ret_val Return output or not.
2960 - *
2961 - * @return mixed
2962 - */
2963 - public static function digitalocean_action_create_backup( $website_id = '', $ret_val = false ) {
3003 + // Return AJAX.
3004 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3005 + if ( '1' !== (string) $api_response->success ) {
3006 + wp_send_json_error( 'false' );
2964 3007
2965 - // Grab $_POST data.
2966 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : $website_id; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3008 + }
3009 + wp_send_json( 'true' );
3010 + }
3011 + }
2967 3012
2968 - // Grab Child Site options.
2969 - $website = Api_Backups_Helper::get_website_by_id( $website_id );
3013 + /**
3014 + * GridPane: action delete backup.
3015 + *
3016 + * Delete backup for the selected GridPane server.
3017 + *
3018 + * @return void
3019 + */
3020 + public function gridpane_action_delete_backup() {
2970 3021
2971 - // Grab IDs from websites.
2972 - $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_instance_id' ) );
2973 - $droplet_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3022 + Api_Backups_Helper::security_nonce( 'gridpane_action_delete_backup' );
2974 3023
2975 - // Grab Access token.
2976 - $accessToken = self::get_digitalocean_api_key();
3024 + // Grab $_POST data.
3025 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3026 + $backup_type = isset( $_POST['backup_type'] ) ? wp_unslash( $_POST['backup_type'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3027 + $backup_name = isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2977 3028
2978 - // Set backup type and name.
2979 - $backup_data = array(
2980 - 'type' => 'snapshot',
2981 - 'name' => 'MainWP API Backups - ' . $website['name'],
2982 - );
2983 - $backup_data = wp_json_encode( $backup_data );
3029 + // Grab backup info from websites.
3030 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3031 + $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2984 3032
2985 - // Send Payload & create backup.
2986 - $api_response = self::call_digitalocean_api( 'POST', '/droplets/' . $droplet_id . '/actions', $accessToken, $backup_data );
3033 + // Grab Gridpane Access token.
3034 + $accessToken = static::get_gridpane_api_key();
2987 3035
2988 - $success = true;
3036 + // Set which Backup to restore to.
3037 + $backup_data = array(
3038 + 'backup_source' => 'local',
3039 + 'backup_type' => $backup_type,
3040 + 'backup' => $backup_name,
3041 + );
3042 + $backup_data = wp_json_encode( $backup_data );
2989 3043
2990 - // Store Last Backup timestamp.
2991 - if ( 'true' === $api_response['status'] ) {
2992 - $local_time = current_datetime();
2993 - $current_time = $local_time->getTimestamp() + $local_time->getOffset();
2994 - Api_Backups_Helper::update_website_option( $website, 'mainwp_3rd_party_digitalocean_last_backup', $current_time );
2995 - } else {
2996 - $success = false;
2997 - }
3044 + // Send Payload & delete backup.
3045 + $api_response = json_decode( static::call_gridpane_api( 'PUT', '/backups/purge/' . $site_id, $accessToken, $backup_data ) );
2998 3046
2999 - if ( $ret_val ) {
3000 - return $api_response;
3001 - }
3047 + // Return AJAX.
3048 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3049 + if ( '1' !== (string) $api_response->success ) {
3050 + wp_send_json_error( 'false' );
3051 + }
3052 + wp_send_json( 'true' );
3053 + }
3054 + }
3002 3055
3003 - // Return AJAX.
3004 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3005 - // Store Last Backup timestamp.
3006 - if ( $success ) {
3007 - wp_send_json( 'true' );
3008 - } else {
3009 - wp_die( 'false' );
3010 - }
3011 - }
3012 - }
3013 3056
3014 - /**
3015 - *
3016 - * DigitalOcean: Action refresh available backups.
3017 - *
3018 - * Save backups to DB for the selected DigitalOcean server.
3019 - *
3020 - * @return void
3021 - */
3022 - public function digitalocean_action_refresh_available_backups() {
3057 + /*********************************************************************************
3058 + * Linode API Methods.
3059 + **********************************************************************************/
3023 3060
3024 - Api_Backups_Helper::security_nonce( 'digitalocean_action_refresh_available_backups' );
3061 + /**
3062 + * Call Linode API, Authenticate & perform given method.
3063 + *
3064 + * Use this function to contact Linode API
3065 + * We use OAuth, an open standard for authorization. Here are the steps involved:
3066 + * 1. Get your API Key from here: https://platform.cloudways.com/api
3067 + * 2. Enter in your account email address and API Key below.
3068 + *
3069 + * @param string $method GET|POST|PUT|DELETE.
3070 + * @param string $url relative URL for the call.
3071 + * @param string $accessToken Access token generated using OAuth Call.
3072 + * @param mixed $backup_data Json encoded array - Optional post data for the call.
3073 + * @return string Output from GridPane API.
3074 + */
3075 + public static function call_linode_api( $method, $url, $accessToken, $backup_data = array() ) {
3025 3076
3026 - // Grab website_id & backup_api name from Ajax post.
3027 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3028 - // Grab $_POST data.
3029 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3030 - } else {
3031 - // Grab $_GET['data'] from url if not Ajax call.
3032 - $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3033 - // $backup_api is pulled from the DB below if not Ajax call.
3034 - }
3077 + $baseurl = 'https://api.linode.com/v4/linode';
3078 + $curl = curl_init();
3079 + curl_setopt_array(
3080 + $curl,
3081 + array(
3082 + CURLOPT_URL => $baseurl . $url,
3083 + CURLOPT_RETURNTRANSFER => true,
3084 + CURLOPT_ENCODING => '',
3085 + CURLOPT_MAXREDIRS => 10,
3086 + CURLOPT_TIMEOUT => 0,
3087 + CURLOPT_FOLLOWLOCATION => true,
3088 + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
3089 + CURLOPT_CUSTOMREQUEST => $method,
3090 + CURLOPT_POSTFIELDS => $backup_data,
3091 + CURLOPT_HTTPHEADER => array(
3092 + "Authorization: Bearer $accessToken",
3093 + 'Content-Type: application/json',
3094 + ),
3095 + )
3096 + );
3035 3097
3036 - // Grab IDs from websites.
3037 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3038 - $droplet_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3098 + $response = curl_exec( $curl );
3039 3099
3040 - // Grab Vultr Access token.
3041 - $accessToken = self::get_digitalocean_api_key();
3100 + curl_close( $curl );
3101 + return $response;
3102 + }
3042 3103
3043 - // Send Payload & create backup.
3044 - $api_response = self::call_digitalocean_api( 'GET', '/droplets/' . $droplet_id . '/snapshots', $accessToken );
3045 - $all_backups = $api_response['response'];
3104 + /**
3105 + * Linode: action create backup.
3106 + *
3107 + * Create backup for the selected Linode server.
3108 + *
3109 + * @return void
3110 + */
3111 + public function ajax_linode_action_individual_create_backup() {
3112 + Api_Backups_Helper::security_nonce( 'linode_action_individual_create_backup' );
3113 + static::linode_action_create_backup();
3114 + die();
3115 + }
3046 3116
3047 - // Grab Site options then update Child Site options.
3048 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_digitalocean_available_backups', $all_backups );
3049 - Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'digitalocean' );
3117 + /**
3118 + * Linode: action create backup.
3119 + *
3120 + * Create backup for the selected Linode server.
3121 + *
3122 + * @return void
3123 + */
3124 + public function ajax_linode_action_create_backup() {
3125 + Api_Backups_Helper::security_nonce( 'linode_action_create_backup' );
3126 + static::linode_action_create_backup();
3127 + die();
3128 + }
3050 3129
3051 - // Return AJAX.
3052 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3053 - // Store Last Backup timestamp.
3054 - if ( 'true' === $api_response['status'] ) {
3055 - wp_send_json( 'true' );
3056 - } else {
3057 - wp_die( 'false' );
3058 - }
3059 - }
3060 - }
3130 + /**
3131 + * Linode: action create backup.
3132 + *
3133 + * Create backup for the selected Linode server.
3134 + *
3135 + * @param int $website_id Website ID.
3136 + * @param bool $ret_val Return output or not.
3137 + *
3138 + * @return mixed
3139 + */
3140 + public static function linode_action_create_backup( $website_id = '', $ret_val = false ) {
3061 3141
3062 - /**
3063 - * DigitalOcean: Action restore backup.
3064 - *
3065 - * Restore a backup of the droplet.
3066 - *
3067 - * @return void
3068 - */
3069 - public function digitalocean_action_restore_backup() {
3142 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : $website_id; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3070 3143
3071 - Api_Backups_Helper::security_nonce( 'digitalocean_action_restore_backup' );
3144 + // Grab IDs from websites.
3145 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3146 + $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3072 3147
3073 - // Grab $_POST data.
3074 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3075 - $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
3148 + // Grab Linode Access token.
3149 + $accessToken = static::get_linode_api_key();
3076 3150
3077 - // Grab IDs from websites.
3078 - $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3079 - $droplet_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3151 + // Send Payload & create backup.
3152 + $linode_response = (array) static::call_linode_api( 'POST', static::INSTANCES . $instance_id . '/backups', $accessToken );
3153 + $linode_response = json_decode( $linode_response[0] );
3080 3154
3081 - // Grab Access token.
3082 - $accessToken = self::get_digitalocean_api_key();
3155 + // Handle response.
3156 + if ( ! isset( $linode_response->errors ) ) {
3157 + $local_time = current_datetime();
3158 + $current_time = $local_time->getTimestamp() + $local_time->getOffset();
3159 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_linode_last_backup', $current_time );
3160 + }
3083 3161
3084 - // Set backup type and name.
3085 - $backup_data = array(
3086 - 'type' => 'restore',
3087 - 'image' => $snapshot_id,
3088 - );
3089 - $backup_data = wp_json_encode( $backup_data );
3162 + if ( $ret_val ) {
3163 + return $linode_response;
3164 + }
3090 3165
3091 - // Send Payload & create backup.
3092 - $api_response = self::call_digitalocean_api( 'POST', '/droplets/' . $droplet_id . '/actions', $accessToken, $backup_data );
3166 + // Handle response.
3167 + if ( isset( $linode_response->errors ) ) {
3168 + $error = new WP_Error( '400', $linode_response->errors['0']->reason );
3169 + // Return AJAX.
3170 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3171 + wp_send_json_error( $error );
3093 3172
3094 - // Return AJAX.
3095 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3096 - // Store Last Backup timestamp.
3097 - if ( 'true' === $api_response['status'] && '201' === $api_response['httpCode'] ) {
3098 - wp_send_json( 'true' );
3099 - } else {
3100 - wp_die( 'false' );
3101 - }
3102 - }
3103 - }
3173 + }
3174 + } elseif ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3175 + wp_send_json( 'true' ); // Return AJAX.
3176 + }
3177 + die();
3178 + }
3104 3179
3105 - /**
3106 - * DigitalOcean: Action delete backup.
3107 - *
3108 - * Delete a backup of the droplet.
3109 - *
3110 - * @return void
3111 - */
3112 - public static function digitalocean_action_delete_backup() {
3180 + /**
3181 + * Linode: action Refresh available backups.
3182 + *
3183 + * Save backups to DB for the selected Linode server.
3184 + *
3185 + * @return void
3186 + */
3187 + public function linode_action_refresh_available_backups() {
3188 + Api_Backups_Helper::security_nonce( 'linode_action_refresh_available_backups' );
3189 + // Grab website_id & backup_api name from Ajax post.
3190 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3191 + // Grab $_POST data.
3192 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3193 + } else {
3194 + // Grab $_GET['data'] from url if not Ajax call.
3195 + $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3196 + }
3113 3197
3114 - Api_Backups_Helper::security_nonce( 'digitalocean_action_delete_backup' );
3198 + // Grab Child Site options.
3199 + // Grab IDs from websites.
3200 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3201 + $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3115 3202
3116 - // Grab $_POST data.
3117 - $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
3203 + // Grab Vultr Access token.
3204 + $accessToken = static::get_linode_api_key();
3118 3205
3119 - // Grab Access token.
3120 - $accessToken = self::get_digitalocean_api_key();
3206 + // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/backups.
3207 + $api_response = (object) static::call_linode_api( 'GET', static::INSTANCES . $instance_id . '/backups', $accessToken );
3208 + $all_backups = $api_response->scalar;
3121 3209
3122 - // Send Payload.
3123 - $api_response = self::call_digitalocean_api( 'DELETE', '/snapshots/' . $snapshot_id, $accessToken );
3210 + // Grab Site options then update Child Site options.
3211 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_linode_available_backups', $all_backups );
3124 3212
3125 - // Return AJAX.
3126 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3127 - if ( '' !== $api_response['response'] && '204' === $api_response['httpCode'] ) {
3128 - wp_send_json_error( 'false' );
3129 - }
3130 - wp_send_json( 'true' );
3131 - }
3132 - }
3213 + Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'linode' );
3133 3214
3134 - /*********************************************************************************
3135 - * Plesk API Methods.
3136 - **********************************************************************************/
3137 - /**
3138 - * Call Plesk API, Authenticate & perform given method.
3139 - *
3140 - * @param string $method GET|POST|PUT|DELETE.
3141 - * @param string $url API endpoint for the call.
3142 - * @param string $baseurl Base url.
3143 - * @param string $api_key Plesk API Key.
3144 - * @param mixed $backup_data Json encoded array - Optional post data for the call.
3145 - * @return array Output from cPanel API.
3146 - */
3147 - public static function call_plesk_api( $method, $url, $baseurl, $api_key, $backup_data = array() ) {
3215 + // Return AJAX.
3216 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3217 + // Store Available backups.
3218 + if ( ! $all_backups ) {
3219 + wp_send_json_error( $api_response );
3220 + } else {
3221 + wp_send_json( 'true' );
3222 + }
3223 + }
3224 + }
3148 3225
3149 - $curl = curl_init();
3226 + /**
3227 + * Linode: action Restore backup.
3228 + *
3229 + * Restore backup for the selected Linode server.
3230 + *
3231 + * @return void
3232 + */
3233 + public function linode_action_restore_backup() {
3150 3234
3151 - $api_Key = $api_key;
3152 - curl_setopt_array(
3153 - $curl,
3154 - array(
3155 - CURLOPT_URL => $baseurl . $url,
3156 - CURLOPT_RETURNTRANSFER => true,
3157 - CURLOPT_ENCODING => '',
3158 - CURLOPT_MAXREDIRS => 10,
3159 - CURLOPT_TIMEOUT => 0,
3160 - CURLOPT_FOLLOWLOCATION => true,
3161 - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
3162 - CURLOPT_CUSTOMREQUEST => $method,
3163 - CURLOPT_POSTFIELDS => $backup_data,
3164 - CURLOPT_HTTPHEADER => array(
3165 - 'Accept: */*', // DO NOT REMOVE THIS LINE! Plesk API will DELETE ALL BACKUPS if this is not included!
3166 - 'Content-Type: application/json',
3167 - "X-API-Key: $api_Key",
3168 - ),
3169 - )
3170 - );
3235 + Api_Backups_Helper::security_nonce( 'linode_action_restore_backup' );
3171 3236
3172 - $resp = curl_exec( $curl );
3237 + // Grab $_POST data.
3238 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3239 + $backup_id = isset( $_POST['backup_id'] ) ? wp_unslash( $_POST['backup_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3173 3240
3174 - $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
3241 + // Grab IDs from websites.
3242 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3243 + $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3175 3244
3176 - $response['httpCode'] = $httpCode;
3177 - $response['response'] = $resp;
3245 + // Grab Linode Access token.
3246 + $accessToken = static::get_linode_api_key();
3178 3247
3179 - if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
3180 - $response['status'] = 'false';
3181 - } else {
3182 - $response['status'] = 'true';
3183 - }
3184 - curl_close( $curl );
3185 - return $response;
3186 - }
3248 + // Set which Backup to restore to.
3249 + $backup_data = array(
3250 + 'instance_id' => $instance_id,
3251 + 'overwrite' => true,
3252 + );
3253 + $backup_data = wp_json_encode( $backup_data );
3187 3254
3188 - /**
3189 - *
3190 - * Plesk: Grab Home Directory.
3191 - *
3192 - * Grab needed home directory for downloading backups.
3193 - *
3194 - * @return string|bool
3195 - */
3196 - public static function get_plesk_home_dir() {
3197 - // Authenticate plesk account.
3198 - $plesk_authentication_credentials = self::get_plesk_authentication_credentials();
3199 - $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3200 - $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3201 - $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3202 - $website_id = $plesk_authentication_credentials[0]['website_id'];
3255 + // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/backups/{backupId}/restore.
3256 + $restore_response = (array) static::call_linode_api( 'POST', static::INSTANCES . $instance_id . '/backups/' . $backup_id . '/restore', $accessToken, $backup_data );
3257 + $restore_response = (array) json_decode( $restore_response['0'] );
3203 3258
3204 - $api_response = self::call_plesk_api( 'GET', '/api/modules/wp-toolkit/v1/installations?installationsIds%5B%5D=' . $plesk_installation_id, $plesk_baseurl, $plesk_api_key );
3259 + sleep( 20 );
3260 + static::linode_action_linode_status( $website_id );
3261 + }
3205 3262
3206 - $response_decoded = ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
3207 - return is_array( $response_decoded ) && ! empty( $response_decoded[0] ) && ! empty( $response_decoded['0']->domain->name ) ? $response_decoded['0']->domain->name : false;
3208 - }
3263 + /**
3264 + * Linode: action Linode status.
3265 + *
3266 + * Check linode status to know when to reboot server.
3267 + *
3268 + * @param int $website_id Child Site ID.
3269 + *
3270 + * @return void
3271 + */
3272 + public static function linode_action_linode_status( $website_id ) {
3209 3273
3210 - /**
3211 - *
3212 - * Plesk: Authentication.
3213 - *
3214 - * Grab needed authentication credentials for Plesk API - either from global settings or individual settings.
3215 - *
3216 - * @param int $website_id Website ID.
3217 - *
3218 - * @return array
3219 - */
3220 - public static function get_plesk_authentication_credentials( $website_id = null ) {
3274 + // Grab IDs from websites.
3275 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3276 + $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3221 3277
3222 - $plesk_authentication_credentials = array();
3223 - // Grab website_id & from Ajax post if $website_id is not set.
3224 - if ( empty( $website_id ) ) {
3225 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3226 - if ( isset( $_POST['website_id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3227 - // Grab $_POST data.
3228 - $website_id = intval( $_POST['website_id'] ); //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3229 - } else {
3230 - // Grab $_GET['data'] from url.
3231 - $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3232 - }
3233 - } else {
3234 - // Grab $_GET['data'] from url.
3235 - $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3236 - }
3237 - }
3278 + // Grab Linode Access token.
3279 + $accessToken = static::get_linode_api_key();
3238 3280
3239 - // Global / Individual check.
3240 - $global_individual_check = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_plesk_individual' ) );
3241 - $mainwp_enable_plesk_individual = isset( $global_individual_check['mainwp_enable_plesk_individual'] ) ? $global_individual_check['mainwp_enable_plesk_individual'] : '0';
3281 + // Send Payload & grab instance status. https://api.linode.com/v4/linode/instances/{linodeId}.
3282 + $linode_instance_response = (array) static::call_linode_api( 'GET', static::INSTANCES . $instance_id, $accessToken );
3283 + $linode_instance_response = json_decode( $linode_instance_response['0'] );
3284 + $linode_instance_status = $linode_instance_response->status;
3242 3285
3243 - if ( 'on' === $mainwp_enable_plesk_individual ) {
3244 - // Grab cPanel baseurl, username & password.
3245 - $baseurl = Api_Backups_Helper::get_website_options( $website_id, array( 'plesk_api_url' ) );
3246 - $plesk_baseurl = isset( $baseurl['plesk_api_url'] ) ? $baseurl['plesk_api_url'] : null;
3286 + // Check if linode status is 'offline'.
3287 + // Check linode status to know when to reboot server.
3288 + switch ( $linode_instance_status ) {
3289 + case 'running':
3290 + case 'restoring':
3291 + case 'Linode Busy.':
3292 + // Re-Check status.
3293 + sleep( 1 );
3294 + static::linode_action_linode_status( $website_id );
3295 + break;
3296 + case 'offline':
3297 + // Starting server.
3298 + static::linode_action_linode_start( $instance_id );
3299 + break;
3300 + default:
3301 + break;
3302 + }
3303 + }
3247 3304
3248 - // Grab Plesk password.
3249 - $plesk_api_key = Api_Backups_Utility::get_instance()->get_child_api_key( $website_id, 'plesk' );
3305 + /**
3306 + * Linode: action Linode start.
3307 + *
3308 + * @param int $instance_id Linode Instance ID.
3309 + *
3310 + * @return void
3311 + */
3312 + public static function linode_action_linode_start( $instance_id ) {
3313 + sleep( 10 );
3314 + // Grab Linode Access token.
3315 + $accessToken = static::get_linode_api_key();
3250 3316
3251 - // Grab Plesk Installation ID.
3252 - $site_path = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_plesk_installation_id' ) );
3253 - $plesk_installation_id = isset( $site_path['mainwp_plesk_installation_id'] ) ? $site_path['mainwp_plesk_installation_id'] : null;
3317 + // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/boot.
3318 + $linode_boot_response = (array) static::call_linode_api( 'POST', static::INSTANCES . $instance_id . '/boot', $accessToken );
3319 + $linode_boot_response = (array) json_decode( $linode_boot_response['0'] );
3254 3320
3255 - } elseif ( '0' === $mainwp_enable_plesk_individual ) {
3256 - // Grab Plesk baseurl, username & password.
3257 - $plesk_baseurl = ( false === get_option( 'mainwp_plesk_api_url' ) ) ? null : get_option( 'mainwp_plesk_api_url' );
3321 + wp_send_json( 'true' );
3322 + }
3258 3323
3259 - // Grab Plesk password.
3260 - $plesk_api_key = self::get_plesk_api_key();
3324 + /**
3325 + * Linode: action cancel backups.
3326 + *
3327 + * Cancel all backups for a Linode Instance.
3328 + *
3329 + * @return void
3330 + */
3331 + public function linode_action_cancel_backups() {
3261 3332
3262 - // Grab Plesk Installation ID.
3263 - $site_path = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_plesk_installation_id' ) );
3264 - $plesk_installation_id = isset( $site_path['mainwp_plesk_installation_id'] ) ? $site_path['mainwp_plesk_installation_id'] : null;
3265 - }
3333 + Api_Backups_Helper::security_nonce( 'linode_action_cancel_backups' );
3266 3334
3267 - // Build array.
3268 - $plesk_authentication_credentials[] = array(
3269 - 'plesk_baseurl' => $plesk_baseurl,
3270 - 'plesk_api_key' => $plesk_api_key,
3271 - 'plesk_installation_id' => $plesk_installation_id,
3272 - 'website_id' => $website_id,
3273 - );
3335 + // Grab $_POST data.
3336 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3274 3337
3275 - return $plesk_authentication_credentials;
3276 - }
3338 + // Grab IDs from websites.
3339 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3340 + $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3277 3341
3278 - /**
3279 - * Plesk: action refresh available backups.
3280 - *
3281 - * Refresh available backups for the selected server.
3282 - *
3283 - * @return void
3284 - */
3285 - public function ajax_plesk_action_refresh_available_backups() {
3286 - Api_Backups_Helper::security_nonce( 'plesk_action_refresh_available_backups' );
3287 - self::plesk_action_refresh_available_backups();
3288 - die();
3289 - }
3342 + // Grab Vultr Access token.
3343 + $accessToken = static::get_linode_api_key();
3290 3344
3291 - /**
3292 - * Plesk: action create backup.
3293 - *
3294 - * Create backup for the selected server.
3295 - *
3296 - * @return void
3297 - */
3298 - public function ajax_plesk_action_create_backup() {
3299 - Api_Backups_Helper::security_nonce( 'plesk_action_create_backup' );
3300 - self::plesk_action_create_backup();
3301 - die();
3302 - }
3345 + // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/backups/cancel.
3346 + $api_response = (object) static::call_linode_api( 'POST', static::INSTANCES . $instance_id . '/backups/cancel', $accessToken );
3303 3347
3304 - /**
3305 - * Plesk: action restore backup.
3306 - *
3307 - * Create backup for the selected server.
3308 - *
3309 - * @return void
3310 - */
3311 - public function ajax_plesk_action_restore_backup() {
3312 - Api_Backups_Helper::security_nonce( 'plesk_action_restore_backup' );
3313 - self::plesk_action_restore_backup();
3314 - die();
3315 - }
3348 + // Return AJAX.
3349 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3350 + // Store Available backups.
3351 + if ( ! $api_response ) {
3352 + wp_send_json_error( 'false' );
3316 3353
3317 - /**
3318 - * Plesk: action delete backup.
3319 - *
3320 - * Delete backup for the selected server.
3321 - *
3322 - * @return void
3323 - */
3324 - public function ajax_plesk_action_delete_backup() {
3325 - Api_Backups_Helper::security_nonce( 'plesk_action_delete_backup' );
3326 - self::plesk_action_delete_backup();
3327 - die();
3328 - }
3354 + } else {
3355 + $all_backups = array();
3356 + // Grab Site options then update Child Site options.
3357 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_linode_available_backups', $all_backups );
3358 + }
3359 + wp_send_json( 'true' );
3360 + }
3361 + }
3329 3362
3330 - /**
3331 - *
3332 - * Plesk: Action refresh available backups.
3333 - *
3334 - * Save backups to DB for the selected server.
3335 - *
3336 - * @return void
3337 - */
3338 - public static function plesk_action_refresh_available_backups() {
3363 + /*********************************************************************************
3364 + * DigitalOcean API Methods.
3365 + **********************************************************************************/
3339 3366
3340 - // Authenticate plesk account.
3341 - $plesk_authentication_credentials = self::get_plesk_authentication_credentials();
3342 - $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3343 - $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3344 - $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3345 - $website_id = $plesk_authentication_credentials[0]['website_id'];
3367 + /**
3368 + * Call DigitalOcean API, Authenticate & perform given method.
3369 + *
3370 + * @param string $method GET|POST|PUT|DELETE.
3371 + * @param string $url relative URL for the call.
3372 + * @param string $accessToken Access token generated using OAuth Call.
3373 + * @param mixed $backup_data Json encoded array - Optional post data for the call.
3374 + * @return array Output from DigitalOcean API.
3375 + */
3376 + public static function call_digitalocean_api( $method, $url, $accessToken, $backup_data = array() ) {
3346 3377
3347 - // Grab backup meta.
3348 - $api_response = self::call_plesk_api( 'GET', '/api/modules/wp-toolkit/v1/installations/' . $plesk_installation_id . '/backups/meta', $plesk_baseurl, $plesk_api_key );
3378 + $baseurl = 'https://api.digitalocean.com/v2';
3349 3379
3350 - $all_backups = $api_response['response'];
3351 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_plesk_available_backups', $all_backups );
3352 - Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'plesk' );
3380 + $curl = curl_init();
3381 + curl_setopt_array(
3382 + $curl,
3383 + array(
3384 + CURLOPT_URL => $baseurl . $url,
3385 + CURLOPT_RETURNTRANSFER => true,
3386 + CURLOPT_ENCODING => '',
3387 + CURLOPT_MAXREDIRS => 10,
3388 + CURLOPT_TIMEOUT => 0,
3389 + CURLOPT_FOLLOWLOCATION => true,
3390 + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
3391 + CURLOPT_CUSTOMREQUEST => $method,
3392 + CURLOPT_POSTFIELDS => $backup_data,
3393 + CURLOPT_HTTPHEADER => array(
3394 + "Authorization: Bearer $accessToken",
3395 + 'Content-Type: application/json',
3396 + ),
3397 + )
3398 + );
3353 3399
3354 - // Return AJAX.
3355 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3356 - // Store Last Backup timestamp.
3357 - if ( 'true' === $api_response['status'] ) {
3358 - wp_send_json( 'true' );
3359 - } else {
3360 - wp_die( 'false' );
3361 - }
3362 - }
3363 - }
3400 + $resp = curl_exec( $curl );
3364 3401
3365 - /**
3366 - *
3367 - * Plesk: Action create manual backup.
3368 - *
3369 - * Create a Plesk Backup.
3370 - *
3371 - * @param bool $ret_val Return output or not.
3372 - * @param int $website_id Website ID.
3373 - *
3374 - * @return mixed
3375 - */
3376 - public static function plesk_action_create_backup( $ret_val = false, $website_id = null ) {
3402 + $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
3403 + $response['httpCode'] = $httpCode;
3404 + $response['response'] = $resp;
3405 + if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
3406 + $response['status'] = 'false';
3407 + } else {
3408 + $response['status'] = 'true';
3377 3409
3378 - // Authenticate plesk account.
3379 - $plesk_authentication_credentials = self::get_plesk_authentication_credentials( $website_id );
3380 - $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3381 - $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3382 - $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3383 - $website_id = $plesk_authentication_credentials[0]['website_id'];
3410 + }
3411 + curl_close( $curl );
3412 + return $response;
3413 + }
3384 3414
3385 - $backup_data = array(
3386 - 'installationId' => $plesk_installation_id,
3387 - );
3388 - $backup_data = wp_json_encode( $backup_data );
3389 3415
3390 - // Send Payload & create backup. https://{your_plesk_url}/api/modules/wp-toolkit/v1/features/backups/creator.
3391 - $api_response = self::call_plesk_api( 'POST', '/api/modules/wp-toolkit/v1/features/backups/creator', $plesk_baseurl, $plesk_api_key, $backup_data );
3416 + /**
3417 + * DigitalOcean: Action create backup.
3418 + *
3419 + * Create a backup of the droplet.
3420 + *
3421 + * @return void
3422 + */
3423 + public function ajax_digitalocean_action_create_backup() {
3424 + Api_Backups_Helper::security_nonce( 'digitalocean_action_create_backup' );
3425 + static::digitalocean_action_create_backup();
3426 + }
3392 3427
3393 - $response_decoded = is_array( $api_response ) && ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
3394 - $errors = ! empty( $response_decoded ) && ! empty( $response_decoded->task->errors ) ? $response_decoded->task->errors : '';
3428 + /**
3429 + * DigitalOcean: Action create backup.
3430 + *
3431 + * Create a backup of the droplet.
3432 + *
3433 + * @return void
3434 + */
3435 + public function ajax_digitalocean_action_individual_create_backup() {
3436 + Api_Backups_Helper::security_nonce( 'digitalocean_action_individual_create_backup' );
3437 + static::digitalocean_action_create_backup();
3438 + }
3395 3439
3396 - $success = false;
3397 - if ( is_array( $api_response ) && isset( $api_response['status'] ) && 'true' === $api_response['status'] ) {
3398 - $success = true;
3399 - }
3440 + /**
3441 + * DigitalOcean: Action create backup.
3442 + *
3443 + * Create a backup of the droplet.
3444 + *
3445 + * @param int $website_id Website ID.
3446 + * @param bool $ret_val Return output or not.
3447 + *
3448 + * @return mixed
3449 + */
3450 + public static function digitalocean_action_create_backup( $website_id = '', $ret_val = false ) {
3400 3451
3401 - if ( empty( $errors ) ) {
3402 - // Save Timestamp.
3403 - $local_time = current_datetime();
3404 - $current_time = $local_time->getTimestamp() + $local_time->getOffset();
3405 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_plesk_last_backup', $current_time );
3406 - }
3452 + // Grab $_POST data.
3453 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : $website_id; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3407 3454
3408 - if ( $ret_val ) {
3409 - return $api_response;
3410 - }
3455 + // Grab Child Site options.
3456 + $website = Api_Backups_Helper::get_website_by_id( $website_id );
3411 3457
3412 - // Return AJAX.
3413 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3414 - // Store Last Backup timestamp.
3415 - if ( $success ) {
3416 - wp_send_json( 'true' );
3417 - } else {
3418 - if ( empty( $errors ) ) {
3419 - $errors = esc_html__( 'Undefined error. Please try again.', 'mainwp' );
3420 - }
3421 - wp_die( esc_html( $errors ) );
3422 - }
3423 - }
3424 - }
3458 + // Grab IDs from websites.
3459 + $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_instance_id' ) );
3460 + $droplet_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3425 3461
3426 - /**
3427 - *
3428 - * Plesk: Action restore backup.
3429 - *
3430 - * Restore Plesk Backup.
3431 - */
3432 - public static function plesk_action_restore_backup() {
3462 + // Grab Access token.
3463 + $accessToken = static::get_digitalocean_api_key();
3433 3464
3434 - // Grab website_id & backup_api name from Ajax post.
3435 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3436 - // Grab $_POST data.
3437 - $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
3438 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3439 - }
3465 + // Set backup type and name.
3466 + $backup_data = array(
3467 + 'type' => 'snapshot',
3468 + 'name' => 'MainWP API Backups - ' . $website['name'],
3469 + );
3470 + $backup_data = wp_json_encode( $backup_data );
3440 3471
3441 - // Authenticate plesk account.
3442 - $plesk_authentication_credentials = self::get_plesk_authentication_credentials( $website_id );
3443 - $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3444 - $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3445 - $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3472 + // Send Payload & create backup.
3473 + $api_response = static::call_digitalocean_api( 'POST', static::DROPLETS . $droplet_id . '/actions', $accessToken, $backup_data );
3446 3474
3447 - $backup_data = array(
3448 - 'installationId' => $plesk_installation_id,
3449 - 'fileName' => $backup_name,
3450 - 'clobber' => 'false',
3451 - 'dropAllDatabaseTables' => 'false',
3452 - );
3475 + $success = true;
3453 3476
3454 - $backup_data = wp_json_encode( $backup_data );
3477 + // Store Last Backup timestamp.
3478 + if ( 'true' === $api_response['status'] ) {
3479 + $local_time = current_datetime();
3480 + $current_time = $local_time->getTimestamp() + $local_time->getOffset();
3481 + Api_Backups_Helper::update_website_option( $website, 'mainwp_3rd_party_digitalocean_last_backup', $current_time );
3482 + } else {
3483 + $success = false;
3484 + }
3455 3485
3456 - // Send Payload & create backup. https://{your_plesk_url}/api/modules/wp-toolkit/v1/features/backups/restorer.
3457 - $api_response = self::call_plesk_api( 'POST', '/api/modules/wp-toolkit/v1/features/backups/restorer', $plesk_baseurl, $plesk_api_key, $backup_data );
3486 + if ( $ret_val ) {
3487 + return $api_response;
3488 + }
3458 3489
3459 - $response_decoded = is_array( $api_response ) && ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
3460 - $errors = ! empty( $response_decoded ) && ! empty( $response_decoded->task->errors ) ? $response_decoded->task->errors : '';
3490 + // Return AJAX.
3491 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3492 + // Store Last Backup timestamp.
3493 + if ( $success ) {
3494 + wp_send_json( 'true' );
3495 + } else {
3496 + wp_die( 'false' );
3497 + }
3498 + }
3499 + }
3461 3500
3462 - // Return AJAX.
3463 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3464 - // Store Last Backup timestamp.
3465 - if ( empty( $errors ) ) {
3466 - wp_send_json( 'true' );
3467 - } else {
3468 - wp_die( esc_html( $errors ) );
3469 - }
3470 - }
3471 - }
3501 + /**
3502 + *
3503 + * DigitalOcean: Action refresh available backups.
3504 + *
3505 + * Save backups to DB for the selected DigitalOcean server.
3506 + *
3507 + * @return void
3508 + */
3509 + public function digitalocean_action_refresh_available_backups() {
3472 3510
3473 - /**
3474 - *
3475 - * Plesk: Action delete backup.
3476 - *
3477 - * Delete Plesk Backup.
3478 - */
3479 - public static function plesk_action_delete_backup() {
3511 + Api_Backups_Helper::security_nonce( 'digitalocean_action_refresh_available_backups' );
3480 3512
3481 - // Grab website_id & backup_api name from Ajax post.
3482 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3483 - // Grab $_POST data.
3484 - $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
3485 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3486 - }
3513 + // Grab website_id & backup_api name from Ajax post.
3514 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3515 + // Grab $_POST data.
3516 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3517 + } else {
3518 + // Grab $_GET['data'] from url if not Ajax call.
3519 + $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3520 + // $backup_api is pulled from the DB below if not Ajax call.
3521 + }
3487 3522
3488 - // Authenticate plesk account.
3489 - $plesk_authentication_credentials = self::get_plesk_authentication_credentials( $website_id );
3490 - $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3491 - $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3492 - $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3523 + // Grab IDs from websites.
3524 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3525 + $droplet_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3493 3526
3494 - $backup_data = wp_json_encode(
3495 - array(
3496 - 'delete' => true,
3497 - )
3498 - );
3527 + // Grab Vultr Access token.
3528 + $accessToken = static::get_digitalocean_api_key();
3499 3529
3500 - /**
3501 - * Payload for deleting a backup.
3502 - * plesk_baseurl must include the port number.
3503 - * https://{plesk_baseurl:8443}/api/modules/wp-toolkit/v1/installations/{plesk_installation_id}/backups?files%5B%5D={backup_name}
3504 - * Backup Name Example ( must be urlencoded ): sweet-lovelace.104-207-132-143.plesk.page_site-1__2024-01-12T16_37_25%2B0000.zip
3505 - */
3530 + // Send Payload & create backup.
3531 + $api_response = static::call_digitalocean_api( 'GET', static::DROPLETS . $droplet_id . '/snapshots', $accessToken );
3532 + $all_backups = $api_response['response'];
3506 3533
3507 - $payload = '/api/modules/wp-toolkit/v1/installations/' . $plesk_installation_id . '/backups?files%5B%5D=' . rawurlencode( $backup_name );
3534 + // Grab Site options then update Child Site options.
3535 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_digitalocean_available_backups', $all_backups );
3536 + Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'digitalocean' );
3508 3537
3509 - // Send Payload & create backup.
3510 - $api_response = self::call_plesk_api( 'DELETE', $payload, $plesk_baseurl, $plesk_api_key, $backup_data );
3538 + // Return AJAX.
3539 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3540 + // Store Last Backup timestamp.
3541 + if ( 'true' === $api_response['status'] ) {
3542 + wp_send_json( 'true' );
3543 + } else {
3544 + wp_die( 'false' );
3545 + }
3546 + }
3547 + }
3511 3548
3512 - $response_decoded = ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
3513 - $errors = ! empty( $response_decoded ) && ! empty( $response_decoded->task->errors ) ? $response_decoded->task->errors : '';
3549 + /**
3550 + * DigitalOcean: Action restore backup.
3551 + *
3552 + * Restore a backup of the droplet.
3553 + *
3554 + * @return void
3555 + */
3556 + public function digitalocean_action_restore_backup() {
3514 3557
3515 - // Return AJAX.
3516 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3517 - // Store Last Backup timestamp.
3518 - if ( empty( $errors ) && '204' === (string) $api_response['httpCode'] && 'true' === (string) $api_response['status'] ) {
3519 - wp_send_json( 'true' );
3520 - } else {
3521 - wp_die( esc_html( $errors ) );
3522 - }
3523 - }
3524 - }
3558 + Api_Backups_Helper::security_nonce( 'digitalocean_action_restore_backup' );
3525 3559
3526 - /*********************************************************************************
3527 - * CPanel API Methods.
3528 - **********************************************************************************/
3529 - /**
3530 - * Call cPanel API, Authenticate & perform given method.
3531 - *
3532 - * @param string $method GET|POST|PUT|DELETE.
3533 - * @param string $url API endpoint for the call.
3534 - * @param string $baseurl Baseurl.
3535 - * @param string $username cPanel account username.
3536 - * @param string $password cPanel account password.
3537 - * @param mixed $backup_data Json encoded array - Optional post data for the call.
3538 - * @return array Output from cPanel API.
3539 - */
3540 - public static function call_cpanel_api( $method, $url, $baseurl, $username, $password, $backup_data = array() ) {
3560 + // Grab $_POST data.
3561 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3562 + $snapshot_id = isset( $_POST['snapshot_id'] ) ? wp_unslash( $_POST['snapshot_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3541 3563
3542 - // base64encode cPanel Username & Password.
3543 - $base64encoded = base64_encode( $username . ':' . $password ); //phpcs:ignore -- base64 encode.
3544 - $curl = curl_init();
3564 + // Grab IDs from websites.
3565 + $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3566 + $droplet_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3545 3567
3546 - curl_setopt_array(
3547 - $curl,
3548 - array(
3549 - CURLOPT_URL => $baseurl . $url,
3550 - CURLOPT_RETURNTRANSFER => true,
3551 - CURLOPT_ENCODING => '',
3552 - CURLOPT_MAXREDIRS => 10,
3553 - CURLOPT_TIMEOUT => 0,
3554 - CURLOPT_FOLLOWLOCATION => true,
3555 - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
3556 - CURLOPT_CUSTOMREQUEST => $method,
3557 - CURLOPT_POSTFIELDS => $backup_data,
3558 - CURLOPT_HTTPHEADER => array(
3559 - 'Content-Type: text/plain',
3560 - "Authorization: Basic $base64encoded",
3561 - ),
3562 - )
3563 - );
3568 + // Grab Access token.
3569 + $accessToken = static::get_digitalocean_api_key();
3564 3570
3565 - $resp = curl_exec( $curl );
3571 + // Set backup type and name.
3572 + $backup_data = array(
3573 + 'type' => 'restore',
3574 + 'image' => $snapshot_id,
3575 + );
3576 + $backup_data = wp_json_encode( $backup_data );
3566 3577
3567 - $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
3568 - $response['httpCode'] = $httpCode;
3569 - $response['response'] = $resp;
3570 - if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
3571 - $response['status'] = 'false';
3572 - } else {
3573 - $response['status'] = 'true';
3574 - }
3575 - curl_close( $curl );
3576 - return $response;
3577 - }
3578 + // Send Payload & create backup.
3579 + $api_response = static::call_digitalocean_api( 'POST', static::DROPLETS . $droplet_id . '/actions', $accessToken, $backup_data );
3578 3580
3579 - /*********************************************************************************
3580 - * CPanel API Methods.
3581 - **********************************************************************************/
3582 - /**
3583 - * Call cPanel API, Authenticate & perform given method.
3584 - *
3585 - * @param string $method GET|POST|PUT|DELETE.
3586 - * @param string $url API endpoint for the call.
3587 - * @param string $baseurl base url.
3588 - * @param string $username cPanel account username.
3589 - * @param string $password cPanel account password.
3590 - * @param mixed $backup_data Json encoded array - Optional post data for the call.
3591 - * @return array Output from cPanel API.
3592 - */
3593 - public static function call_cpanel_api_json( $method, $url, $baseurl, $username, $password, $backup_data = array() ) {
3581 + // Return AJAX.
3582 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3583 + // Store Last Backup timestamp.
3584 + if ( 'true' === $api_response['status'] && '201' === $api_response['httpCode'] ) {
3585 + wp_send_json( 'true' );
3586 + } else {
3587 + wp_die( 'false' );
3588 + }
3589 + }
3590 + }
3594 3591
3595 - // base64encode cPanel Username & Password.
3596 - $base64encoded = base64_encode( $username . ':' . $password ); //phpcs:ignore -- base64 encode.
3597 - $curl = curl_init();
3592 + /**
3593 + * DigitalOcean: Action delete backup.
3594 + *
3595 + * Delete a backup of the droplet.
3596 + *
3597 + * @return void
3598 + */
3599 + public static function digitalocean_action_delete_backup() {
3598 3600
3599 - curl_setopt_array(
3600 - $curl,
3601 - array(
3602 - CURLOPT_URL => $baseurl . $url,
3603 - CURLOPT_RETURNTRANSFER => true,
3604 - CURLOPT_ENCODING => '',
3605 - CURLOPT_MAXREDIRS => 10,
3606 - CURLOPT_TIMEOUT => 0,
3607 - CURLOPT_FOLLOWLOCATION => true,
3608 - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
3609 - CURLOPT_CUSTOMREQUEST => $method,
3610 - CURLOPT_POSTFIELDS => $backup_data,
3611 - CURLOPT_HTTPHEADER => array(
3612 - 'Accept: */*', // DO NOT REMOVE THIS LINE! Plesk API will DELETE ALL BACKUPS if this is not included!
3613 - 'Content-Type: application/json',
3614 - "Authorization: Basic $base64encoded",
3615 - ),
3616 - )
3617 - );
3601 + Api_Backups_Helper::security_nonce( 'digitalocean_action_delete_backup' );
3618 3602
3619 - $resp = curl_exec( $curl );
3603 + // Grab $_POST data.
3604 + $snapshot_id = isset( $_POST['snapshot_id'] ) ? wp_unslash( $_POST['snapshot_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3620 3605
3621 - $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
3622 - $response['httpCode'] = $httpCode;
3623 - $response['response'] = $resp;
3624 - if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
3625 - $response['status'] = 'false';
3626 - } else {
3627 - $response['status'] = 'true';
3628 - }
3629 - curl_close( $curl );
3630 - return $response;
3631 - }
3606 + // Grab Access token.
3607 + $accessToken = static::get_digitalocean_api_key();
3632 3608
3633 - /**
3634 - *
3635 - * CPanel: Authentication.
3636 - *
3637 - * Grab needed authentication credentials for cPanel API - either from global settings or individual settings.
3638 - *
3639 - * @param int $website_id Website ID.
3640 - *
3641 - * @return array
3642 - */
3643 - public static function get_cpanel_authentication_credentials( $website_id = '' ) {
3609 + // Send Payload.
3610 + $api_response = static::call_digitalocean_api( 'DELETE', static::SNAPSHOTS . $snapshot_id, $accessToken );
3644 3611
3645 - $cpanel_authentication_credentials = array();
3612 + // Return AJAX.
3613 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3614 + if ( '' !== $api_response['response'] && '204' === $api_response['httpCode'] ) {
3615 + wp_send_json_error( 'false' );
3616 + }
3617 + wp_send_json( 'true' );
3618 + }
3619 + }
3646 3620
3647 - // Grab website_id & from Ajax post if $website_id is not set.
3648 - if ( empty( $website_id ) ) {
3649 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3650 - // Grab $_POST data.
3651 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3652 - } else {
3653 - // Grab $_GET['data'] from url if not Ajax call.
3654 - $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3655 - }
3656 - }
3621 + /*********************************************************************************
3622 + * Plesk API Methods.
3623 + **********************************************************************************/
3624 + /**
3625 + * Call Plesk API, Authenticate & perform given method.
3626 + *
3627 + * @param string $method GET|POST|PUT|DELETE.
3628 + * @param string $url API endpoint for the call.
3629 + * @param string $baseurl Base url.
3630 + * @param string $api_key Plesk API Key.
3631 + * @param mixed $backup_data Json encoded array - Optional post data for the call.
3632 + * @return array Output from cPanel API.
3633 + */
3634 + public static function call_plesk_api( $method, $url, $baseurl, $api_key, $backup_data = array() ) {
3657 3635
3658 - // Global / Individual check.
3659 - $global_individual_check = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_cpanel_individual' ) );
3660 - $mainwp_enable_cpanel_individual = isset( $global_individual_check['mainwp_enable_cpanel_individual'] ) ? $global_individual_check['mainwp_enable_cpanel_individual'] : '0';
3636 + // To fix double slash issue in url if exists. If url starts with / and baseurl ends with /, then remove the last slash from baseurl.
3637 + if ( '/' === substr( $url, 0, 1 ) && '/' === substr( $baseurl, -1 ) ) {
3638 + $baseurl = rtrim( $baseurl, '/' );
3639 + }
3661 3640
3662 - if ( 'on' === $mainwp_enable_cpanel_individual ) {
3663 - // Grab cPanel baseurl, username & password.
3664 - $baseurl = Api_Backups_Helper::get_website_options( $website_id, array( 'cpanel_api_url' ) );
3665 - $cpanel_baseurl = isset( $baseurl['cpanel_api_url'] ) ? $baseurl['cpanel_api_url'] : null;
3641 + $full_url = $baseurl . $url;
3666 3642
3667 - // Grab cPanel username.
3668 - $username = Api_Backups_Helper::get_website_options( $website_id, array( 'cpanel_account_username' ) );
3669 - $cpanel_username = isset( $username['cpanel_account_username'] ) ? $username['cpanel_account_username'] : null;
3643 + $curl = curl_init();
3670 3644
3671 - // Grab cPanel password.
3672 - $cpanel_password = Api_Backups_Utility::get_instance()->get_child_api_key( $website_id, 'cpanel' );
3645 + $api_Key = $api_key;
3646 + curl_setopt_array(
3647 + $curl,
3648 + array(
3649 + CURLOPT_URL => $full_url,
3650 + CURLOPT_RETURNTRANSFER => true,
3651 + CURLOPT_ENCODING => '',
3652 + CURLOPT_MAXREDIRS => 10,
3653 + CURLOPT_TIMEOUT => 0,
3654 + CURLOPT_FOLLOWLOCATION => true,
3655 + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
3656 + CURLOPT_CUSTOMREQUEST => $method,
3657 + CURLOPT_POSTFIELDS => $backup_data,
3658 + CURLOPT_HTTPHEADER => array(
3659 + 'Accept: */*', // DO NOT REMOVE THIS LINE! Plesk API will DELETE ALL BACKUPS if this is not included!
3660 + 'Content-Type: application/json',
3661 + "X-API-Key: $api_Key",
3662 + ),
3663 + )
3664 + );
3673 3665
3674 - // Grab cPanel site path.
3675 - $site_path = Api_Backups_Helper::get_website_options( $website_id, array( 'cpanel_site_path' ) );
3676 - $cpanel_site_path = isset( $site_path['cpanel_site_path'] ) ? $site_path['cpanel_site_path'] : null;
3666 + $resp = curl_exec( $curl );
3677 3667
3678 - } elseif ( '0' === $mainwp_enable_cpanel_individual ) {
3679 - // Grab cPanel baseurl, username & password.
3680 - $cpanel_baseurl = get_option( 'mainwp_cpanel_url' ); // Fixing when mergeing ???.
3681 - // Grab cPanel username.
3682 - $cpanel_username = get_option( 'mainwp_cpanel_account_username' ); // Fixing when mergeing ???.
3683 - // Grab cPanel password.
3684 - $cpanel_password = self::get_cpanel_account_password();
3668 + $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
3685 3669
3686 - // Grab cPanel site path.
3687 - $cpanel_site_path = ( false === get_option( 'mainwp_cpanel_site_path' ) ) ? null : get_option( 'mainwp_cpanel_site_path' );
3688 - }
3670 + $response['httpCode'] = $httpCode;
3671 + $response['response'] = $resp;
3689 3672
3690 - // Build array.
3691 - $cpanel_authentication_credentials[] = array(
3692 - 'cpanel_baseurl' => $cpanel_baseurl,
3693 - 'cpanel_username' => $cpanel_username,
3694 - 'cpanel_password' => $cpanel_password,
3695 - 'cpanel_site_path' => $cpanel_site_path,
3696 - 'website_id' => $website_id,
3697 - );
3673 + if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
3674 + $response['status'] = 'false';
3675 + } else {
3676 + $response['status'] = 'true';
3677 + }
3678 + curl_close( $curl );
3679 + return $response;
3680 + }
3698 3681
3699 - return $cpanel_authentication_credentials;
3700 - }
3682 + /**
3683 + *
3684 + * Plesk: Grab Home Directory.
3685 + *
3686 + * Grab needed home directory for downloading backups.
3687 + *
3688 + * @return string|bool
3689 + */
3690 + public static function get_plesk_home_dir() {
3691 + // Authenticate plesk account.
3692 + $plesk_authentication_credentials = static::get_plesk_authentication_credentials();
3693 + $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3694 + $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3695 + $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3701 3696
3702 - /**
3703 - *
3704 - * CPanel: Action get cPanel Home Directory.
3705 - *
3706 - * Grab cPanel Home Directory for manual backup links.
3707 - *
3708 - * @return string
3709 - */
3710 - public static function cpanel_action_get_home_directory() {
3697 + $api_response = static::call_plesk_api( 'GET', '/api/modules/wp-toolkit/v1/installations?installationsIds%5B%5D=' . $plesk_installation_id, $plesk_baseurl, $plesk_api_key );
3711 3698
3712 - // Authenticate cPanel account.
3713 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
3714 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
3715 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
3716 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
3699 + $response_decoded = ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
3700 + return is_array( $response_decoded ) && ! empty( $response_decoded[0] ) && ! empty( $response_decoded['0']->domain->name ) ? $response_decoded['0']->domain->name : false;
3701 + }
3717 3702
3718 - // Send Payload.
3719 - $api_response = self::call_cpanel_api( 'GET', '/execute/Variables/get_user_information', $cpanel_baseurl, $cpanel_username, $cpanel_password );
3720 - $api_response_decoded = json_decode( $api_response['response'] );
3703 + /**
3704 + *
3705 + * Plesk: Authentication.
3706 + *
3707 + * Grab needed authentication credentials for Plesk API - either from global settings or individual settings.
3708 + *
3709 + * @param int $website_id Website ID.
3710 + *
3711 + * @return array
3712 + */
3713 + public static function get_plesk_authentication_credentials( $website_id = null ) { //phpcs:ignore -- NOSONAR - complex.
3721 3714
3722 - if ( is_object( $api_response_decoded ) && isset( $api_response_decoded->data->home ) ) {
3723 - $cpanel_home_directory = $api_response_decoded->data->home;
3724 - } else {
3725 - $cpanel_home_directory = '';
3726 - }
3715 + $plesk_authentication_credentials = array();
3716 + // Grab website_id & from Ajax post if $website_id is not set.
3717 + if ( empty( $website_id ) ) {
3718 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3719 + if ( isset( $_POST['website_id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3720 + // Grab $_POST data.
3721 + $website_id = intval( $_POST['website_id'] ); //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3722 + } else {
3723 + // Grab $_GET['data'] from url.
3724 + $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3725 + }
3726 + } else {
3727 + // Grab $_GET['data'] from url.
3728 + $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3729 + }
3730 + }
3727 3731
3728 - return $cpanel_home_directory;
3729 - }
3732 + // Global / Individual check.
3733 + $global_individual_check = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_plesk_individual' ) );
3734 + $mainwp_enable_plesk_individual = isset( $global_individual_check['mainwp_enable_plesk_individual'] ) ? $global_individual_check['mainwp_enable_plesk_individual'] : '0';
3730 3735
3731 - /**
3732 - * Get cPanel manual account backups.
3733 - *
3734 - * @return false|string cPanel account backups
3735 - */
3736 - public static function get_cpanel_manual_account_backups() {
3736 + if ( 'on' === $mainwp_enable_plesk_individual ) {
3737 + // Grab cPanel baseurl, username & password.
3738 + $baseurl = Api_Backups_Helper::get_website_options( $website_id, array( 'plesk_api_url' ) );
3739 + $plesk_baseurl = isset( $baseurl['plesk_api_url'] ) ? $baseurl['plesk_api_url'] : null;
3737 3740
3738 - // Define array for Manual Backups.
3739 - $manual_backups = array();
3741 + // Grab Plesk password.
3742 + $plesk_api_key = Api_Backups_Utility::get_instance()->get_child_api_key( $website_id, 'plesk' );
3740 3743
3741 - // Authenticate cPanel account.
3742 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
3743 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
3744 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
3745 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
3744 + // Grab Plesk Installation ID.
3745 + $site_path = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_plesk_installation_id' ) );
3746 + $plesk_installation_id = isset( $site_path['mainwp_plesk_installation_id'] ) ? $site_path['mainwp_plesk_installation_id'] : null;
3746 3747
3747 - // Send Payload.
3748 - $api_response = self::call_cpanel_api( 'GET', '/execute/Fileman/list_files?dir=/&include_mime=1&types=file', $cpanel_baseurl, $cpanel_username, $cpanel_password );
3749 - $api_response_decoded = json_decode( $api_response['response'] );
3748 + } elseif ( '0' === $mainwp_enable_plesk_individual ) {
3749 + // Grab Plesk baseurl, username & password.
3750 + $plesk_baseurl = ( false === get_option( 'mainwp_plesk_api_url' ) ) ? null : get_option( 'mainwp_plesk_api_url' );
3750 3751
3751 - // Build list.
3752 - if ( is_object( $api_response_decoded ) && isset( $api_response_decoded->data ) ) {
3753 - $files = $api_response_decoded->data;
3754 - foreach ( $files as $file ) {
3755 - if ( 'application/x-gzip' === $file->rawmimetype ) {
3756 - $manual_backups[] = array(
3757 - 'file_name' => $file->file,
3758 - 'absolute_dir' => $file->absdir,
3759 - 'timestamp' => $file->ctime,
3760 - );
3761 - }
3762 - }
3763 - } else {
3764 - $manual_backups = array();
3765 - }
3752 + // Grab Plesk password.
3753 + $plesk_api_key = static::get_plesk_api_key();
3766 3754
3767 - // return array of Manual Backups.
3768 - return wp_json_encode( $manual_backups );
3769 - }
3755 + // Grab Plesk Installation ID.
3756 + $site_path = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_plesk_installation_id' ) );
3757 + $plesk_installation_id = isset( $site_path['mainwp_plesk_installation_id'] ) ? $site_path['mainwp_plesk_installation_id'] : null;
3758 + }
3770 3759
3771 - /**
3772 - * Get cPanel manual database backups.
3773 - *
3774 - * Create manual database backup via mysqldump.
3775 - * Backups will be stored within `/uploads/mainwp/api_db_backups` directory.
3776 - *
3777 - * @param int $website_id Website ID.
3778 - *
3779 - * @return false|string cPanel account backups
3780 - */
3781 - public static function get_cpanel_manual_database_backups( $website_id = '' ) {
3760 + // Build array.
3761 + $plesk_authentication_credentials[] = array(
3762 + 'plesk_baseurl' => $plesk_baseurl,
3763 + 'plesk_api_key' => $plesk_api_key,
3764 + 'plesk_installation_id' => $plesk_installation_id,
3765 + 'website_id' => $website_id,
3766 + );
3782 3767
3783 - // Define array for Manual Backups.
3784 - $manual_backups = array();
3768 + return $plesk_authentication_credentials;
3769 + }
3785 3770
3786 - // Grab Child Site options.
3787 - $website = Api_Backups_Helper::get_website_by_id( $website_id );
3771 + /**
3772 + * Plesk: action refresh available backups.
3773 + *
3774 + * Refresh available backups for the selected server.
3775 + *
3776 + * @return void
3777 + */
3778 + public function ajax_plesk_action_refresh_available_backups() {
3779 + Api_Backups_Helper::security_nonce( 'plesk_action_refresh_available_backups' );
3780 + static::plesk_action_refresh_available_backups();
3781 + die();
3782 + }
3788 3783
3789 - // Authenticate cPanel account.
3790 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
3791 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
3792 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
3793 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
3784 + /**
3785 + * Plesk: action create backup.
3786 + *
3787 + * Create backup for the selected server.
3788 + *
3789 + * @return void
3790 + */
3791 + public function ajax_plesk_action_create_backup() {
3792 + Api_Backups_Helper::security_nonce( 'plesk_action_create_backup' );
3793 + static::plesk_action_create_backup();
3794 + die();
3795 + }
3794 3796
3795 - // Grab cPanel site path.
3796 - $cpanel_db_backups_path = $cpanel_authentication_credentials[0]['cpanel_site_path'] . '/wp-content/uploads/mainwp/api_db_backups';
3797 + /**
3798 + * Plesk: action restore backup.
3799 + *
3800 + * Create backup for the selected server.
3801 + *
3802 + * @return void
3803 + */
3804 + public function ajax_plesk_action_restore_backup() {
3805 + Api_Backups_Helper::security_nonce( 'plesk_action_restore_backup' );
3806 + static::plesk_action_restore_backup();
3807 + die();
3808 + }
3797 3809
3798 - // Send Payload.
3799 - $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 );
3800 - $api_response_decoded = json_decode( $api_response['response'] );
3810 + /**
3811 + * Plesk: action delete backup.
3812 + *
3813 + * Delete backup for the selected server.
3814 + *
3815 + * @return void
3816 + */
3817 + public function ajax_plesk_action_delete_backup() {
3818 + Api_Backups_Helper::security_nonce( 'plesk_action_delete_backup' );
3819 + static::plesk_action_delete_backup();
3820 + die();
3821 + }
3801 3822
3802 - // Build list.
3803 - if ( is_object( $api_response_decoded ) && isset( $api_response_decoded->data ) ) {
3804 - $files = $api_response_decoded->data;
3805 - foreach ( $files as $file ) {
3806 - if ( 'application/x-gzip' === $file->rawmimetype ) {
3807 - $manual_backups[] = array(
3808 - 'file_name' => $file->file,
3809 - 'absolute_dir' => $file->absdir,
3810 - 'timestamp' => $file->ctime,
3811 - );
3812 - }
3813 - }
3814 - } else {
3815 - $manual_backups = array();
3816 - }
3823 + /**
3824 + *
3825 + * Plesk: Action refresh available backups.
3826 + *
3827 + * Save backups to DB for the selected server.
3828 + *
3829 + * @return void
3830 + */
3831 + public static function plesk_action_refresh_available_backups() {
3817 3832
3818 - // return array of Manual Backups.
3819 - return wp_json_encode( $manual_backups );
3820 - }
3833 + // Authenticate plesk account.
3834 + $plesk_authentication_credentials = static::get_plesk_authentication_credentials();
3835 + $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3836 + $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3837 + $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3838 + $website_id = $plesk_authentication_credentials[0]['website_id'];
3821 3839
3822 - /**
3823 - *
3824 - * CPanel: Action refresh available WP-Toolit backups.
3825 - *
3826 - * Save backups to DB for the selected server.
3827 - *
3828 - * @param int $website_id Website id.
3829 - *
3830 - * @return array
3831 - */
3832 - public function get_cpanel_wp_toolkit_backups( $website_id ) {
3840 + // Grab backup meta.
3841 + $api_response = static::call_plesk_api( 'GET', '/api/modules/wp-toolkit/v1/installations/' . $plesk_installation_id . '/backups/meta', $plesk_baseurl, $plesk_api_key );
3833 3842
3834 - // Grab Child Site options array.
3835 - $website = Api_Backups_Helper::get_website_by_id( $website_id );
3843 + $all_backups = $api_response['response'];
3844 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_plesk_available_backups', $all_backups );
3845 + Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'plesk' );
3836 3846
3837 - // Grab website url & trim trailing slash.
3838 - $website_url = trim( $website['url'], '/' );
3847 + // Return AJAX.
3848 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3849 + // Store Last Backup timestamp.
3850 + if ( 'true' === $api_response['status'] ) {
3851 + wp_send_json( 'true' );
3852 + } else {
3853 + wp_die( 'false' );
3854 + }
3855 + }
3856 + }
3839 3857
3840 - // Authenticate cPanel account.
3841 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
3842 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
3843 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
3844 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
3858 + /**
3859 + *
3860 + * Plesk: Action create manual backup.
3861 + *
3862 + * Create a Plesk Backup.
3863 + *
3864 + * @param bool $ret_val Return output or not.
3865 + * @param int $website_id Website ID.
3866 + *
3867 + * @return mixed
3868 + */
3869 + public static function plesk_action_create_backup( $ret_val = false, $website_id = null ) { //phpcs:ignore -- NOSONAR - complex.
3845 3870
3846 - $wp_toolkit_installation_id = '';
3871 + // Authenticate plesk account.
3872 + $plesk_authentication_credentials = static::get_plesk_authentication_credentials( $website_id );
3873 + $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3874 + $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3875 + $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3876 + $website_id = $plesk_authentication_credentials[0]['website_id'];
3847 3877
3848 - // Grab list of WP Toolkit installations.
3849 - $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 );
3850 - $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
3878 + $backup_data = array(
3879 + 'installationId' => $plesk_installation_id,
3880 + );
3881 + $backup_data = wp_json_encode( $backup_data );
3851 3882
3852 - // Search for website url in list of WP Toolkit installations & grab Site ID.
3853 - if ( is_array( $wp_toolkit_installation_list_decoded ) ) {
3854 - foreach ( $wp_toolkit_installation_list_decoded as $site ) {
3855 - if ( $site->url === $website_url ) {
3856 - $wp_toolkit_installation_id = $site->id;
3857 - }
3858 - }
3859 - }
3883 + // Send Payload & create backup. https://{your_plesk_url}/api/modules/wp-toolkit/v1/features/backups/creator.
3884 + $api_response = static::call_plesk_api( 'POST', '/api/modules/wp-toolkit/v1/features/backups/creator', $plesk_baseurl, $plesk_api_key, $backup_data );
3860 3885
3861 - // Grab backup meta for found Site ID.
3862 - $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 );
3863 - if ( 'true' === $wp_toolkit_backups['status'] ) {
3864 - return $wp_toolkit_backups['response'];
3865 - } else {
3866 - return array();
3867 - }
3868 - }
3886 + $response_decoded = is_array( $api_response ) && ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
3887 + $errors = ! empty( $response_decoded ) && ! empty( $response_decoded->task->errors ) ? $response_decoded->task->errors : '';
3869 3888
3870 - /**
3871 - * CPanel: action restore backup.
3872 - *
3873 - * Restore cPanel backup for the selected cPanel server.
3874 - *
3875 - * @return void
3876 - */
3877 - public function ajax_cpanel_action_restore_backup() {
3878 - Api_Backups_Helper::security_nonce( 'cpanel_action_restore_backup' );
3879 - self::cpanel_action_restore_backup();
3880 - die();
3881 - }
3889 + $success = false;
3890 + if ( is_array( $api_response ) && isset( $api_response['status'] ) && 'true' === $api_response['status'] ) {
3891 + $success = true;
3892 + }
3882 3893
3883 - /**
3884 - * CPanel: action restore database backup.
3885 - *
3886 - * Restore cPanel backup for the selected cPanel server.
3887 - *
3888 - * @return void
3889 - */
3890 - public function ajax_cpanel_action_restore_database_backup() {
3891 - Api_Backups_Helper::security_nonce( 'cpanel_action_restore_database_backup' );
3892 - self::cpanel_action_restore_database_backup();
3893 - die();
3894 - }
3894 + if ( empty( $errors ) ) {
3895 + // Save Timestamp.
3896 + $local_time = current_datetime();
3897 + $current_time = $local_time->getTimestamp() + $local_time->getOffset();
3898 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_plesk_last_backup', $current_time );
3899 + }
3895 3900
3896 - /**
3897 - * CPanel: action restore manual backup.
3898 - *
3899 - * Restore cPanel backup for the selected cPanel server.
3900 - *
3901 - * @return void
3902 - */
3903 - public function ajax_cpanel_action_restore_manual_backup() {
3904 - Api_Backups_Helper::security_nonce( 'cpanel_action_restore_manual_backup' );
3905 - self::cpanel_action_restore_manual_backup();
3906 - die();
3907 - }
3901 + if ( $ret_val ) {
3902 + return $api_response;
3903 + }
3908 3904
3909 - /**
3910 - * CPanel: action refresh available backups.
3911 - *
3912 - * Refresh available backups for the selected cPanel server.
3913 - *
3914 - * @return void
3915 - */
3916 - public function ajax_cpanel_action_refresh_available_backups() {
3917 - Api_Backups_Helper::security_nonce( 'cpanel_action_refresh_available_backups' );
3918 - self::cpanel_action_refresh_available_backups();
3919 - die();
3920 - }
3905 + // Return AJAX.
3906 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3907 + // Store Last Backup timestamp.
3908 + if ( $success ) {
3909 + wp_send_json( 'true' );
3910 + } else {
3911 + if ( empty( $errors ) ) {
3912 + $errors = esc_html__( 'Undefined error. Please try again.', 'mainwp' );
3913 + }
3914 + wp_die( esc_html( $errors ) );
3915 + }
3916 + }
3917 + }
3921 3918
3922 - /**
3923 - * CPanel: action create backup.
3924 - *
3925 - * Create backup for the selected cPanel server.
3926 - *
3927 - * @return void
3928 - */
3929 - public function ajax_cpanel_action_create_manual_backup() {
3930 - Api_Backups_Helper::security_nonce( 'cpanel_action_create_manual_backup' );
3931 - self::cpanel_action_create_manual_backup();
3932 - die();
3933 - }
3919 + /**
3920 + *
3921 + * Plesk: Action restore backup.
3922 + *
3923 + * Restore Plesk Backup.
3924 + */
3925 + public static function plesk_action_restore_backup() {
3934 3926
3935 - /**
3936 - * CPanel: action create WP-Toolkit backup.
3937 - *
3938 - * Create backup for the selected cPanel server.
3939 - *
3940 - * @return void
3941 - */
3942 - public function ajax_cpanel_action_create_wptk_backup() {
3943 - Api_Backups_Helper::security_nonce( 'cpanel_action_create_wptk_backup' );
3944 - self::cpanel_action_create_wptk_backup();
3945 - die();
3946 - }
3927 + // Grab website_id & backup_api name from Ajax post.
3928 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3929 + // Grab $_POST data.
3930 + $backup_name = isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3931 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3932 + }
3947 3933
3948 - /**
3949 - * CPanel: action create WP-Toolkit backup.
3950 - *
3951 - * Create backup for the selected cPanel server.
3952 - *
3953 - * @return void
3954 - */
3955 - public function ajax_cpanel_action_restore_wptk_backup() {
3956 - Api_Backups_Helper::security_nonce( 'cpanel_action_restore_wptk_backup' );
3957 - self::cpanel_action_restore_wptk_backup();
3958 - die();
3959 - }
3934 + // Authenticate plesk account.
3935 + $plesk_authentication_credentials = static::get_plesk_authentication_credentials( $website_id );
3936 + $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3937 + $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3938 + $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3960 3939
3961 - /**
3962 - * CPanel: action delete WP-Toolkit backup.
3963 - *
3964 - * Create backup for the selected cPanel server.
3965 - *
3966 - * @return void
3967 - */
3968 - public function ajax_cpanel_action_delete_wptk_backup() {
3969 - Api_Backups_Helper::security_nonce( 'cpanel_action_delete_wptk_backup' );
3970 - self::cpanel_action_delete_wptk_backup();
3971 - die();
3972 - }
3940 + $backup_data = array(
3941 + 'installationId' => $plesk_installation_id,
3942 + 'fileName' => $backup_name,
3943 + 'clobber' => 'false',
3944 + 'dropAllDatabaseTables' => 'false',
3945 + );
3973 3946
3974 - /**
3975 - * CPanel: action create full backup.
3976 - *
3977 - * Create backup for the selected cPanel server.
3978 - *
3979 - * @return void
3980 - */
3981 - public static function ajax_cpanel_action_create_full_backup() {
3982 - Api_Backups_Helper::security_nonce( 'cpanel_action_create_full_backup' );
3947 + $backup_data = wp_json_encode( $backup_data );
3983 3948
3984 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3985 - // Grab Child Site ID from $_POST data.
3986 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3949 + // Send Payload & create backup. https://{your_plesk_url}/api/modules/wp-toolkit/v1/features/backups/restorer.
3950 + $api_response = static::call_plesk_api( 'POST', '/api/modules/wp-toolkit/v1/features/backups/restorer', $plesk_baseurl, $plesk_api_key, $backup_data );
3987 3951
3988 - $opts = Api_Backups_Helper::get_website_options(
3989 - $website_id,
3990 - array(
3991 - 'mainwp_enable_wp_toolkit',
3992 - )
3993 - );
3952 + $response_decoded = is_array( $api_response ) && ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
3953 + $errors = ! empty( $response_decoded ) && ! empty( $response_decoded->task->errors ) ? $response_decoded->task->errors : '';
3994 3954
3995 - $mainwp_enable_wp_toolkit = '';
3955 + // Return AJAX.
3956 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3957 + // Store Last Backup timestamp.
3958 + if ( empty( $errors ) ) {
3959 + wp_send_json( 'true' );
3960 + } else {
3961 + wp_die( esc_html( $errors ) );
3962 + }
3963 + }
3964 + }
3996 3965
3997 - if ( is_array( $opts ) ) {
3998 - $mainwp_enable_wp_toolkit = $opts['mainwp_enable_wp_toolkit'] ?? '0';
3999 - }
3966 + /**
3967 + *
3968 + * Plesk: Action delete backup.
3969 + *
3970 + * Delete Plesk Backup.
3971 + */
3972 + public static function plesk_action_delete_backup() {
4000 3973
4001 - // Create file backup.
4002 - $file_backup_response = self::cpanel_action_create_manual_backup( true );
4003 - $response_decoded = json_decode( $file_backup_response['response'] );
4004 - $errors = $response_decoded->errors['0'];
3974 + // Grab website_id & backup_api name from Ajax post.
3975 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3976 + // Grab $_POST data.
3977 + $backup_name = isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3978 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3979 + }
4005 3980
4006 - // If no errors with file backup, create database backup.
4007 - if ( empty( $errors ) ) {
3981 + // Authenticate plesk account.
3982 + $plesk_authentication_credentials = static::get_plesk_authentication_credentials( $website_id );
3983 + $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3984 + $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3985 + $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
4008 3986
4009 - // If no errors, create database backup.
4010 - $database_backup_response = self::ajax_cpanel_action_create_database_backup( true, $website_id );
3987 + $backup_data = wp_json_encode(
3988 + array(
3989 + 'delete' => true,
3990 + )
3991 + );
4011 3992
4012 - // If no errors, & WP-Toolikit is enabled create WP-Toolkit backup or return true.
4013 - if ( 'GOOD' === $database_backup_response['result'] ) {
4014 - // If WP Toolkit is enabled, create WP Toolkit backup.
4015 - if ( 'on' === $mainwp_enable_wp_toolkit ) {
4016 - $cpanel_wptk_backup_response = self::cpanel_action_create_wptk_backup( true );
4017 - if ( '201' !== $cpanel_wptk_backup_response['httpCode'] && '200' !== $cpanel_wptk_backup_response['httpCode'] && '204' !== $cpanel_wptk_backup_response['httpCode'] ) {
4018 - wp_die( 'There was an issue while creating the Database backup. Please check logs and try again.' );
4019 - } else {
4020 - // Return true for WP-Toolkit backup.
4021 - wp_send_json( 'true' );
4022 - }
4023 - } else {
4024 - // Return true for cPanel backup.
4025 - wp_send_json( 'true' );
4026 - }
4027 - } else {
4028 - // Return error for cPanel database backup.
4029 - wp_die( 'There was an issue while creating the Cpanel Database backup. Please check logs and try again.' );
4030 - }
4031 - } else {
4032 - // If cpanel file backup errors, return false.
4033 - wp_die( esc_html( $errors ) );
4034 - }
4035 - }
4036 - }
3993 + /**
3994 + * Payload for deleting a backup.
3995 + * plesk_baseurl must include the port number.
3996 + * https://{plesk_baseurl:8443}/api/modules/wp-toolkit/v1/installations/{plesk_installation_id}/backups?files%5B%5D={backup_name}
3997 + * Backup Name Example ( must be urlencoded ): sweet-lovelace.104-207-132-143.plesk.page_site-1__2024-01-12T16_37_25%2B0000.zip
3998 + */
4037 3999
4038 - /**
4039 - * CPanel: action create database backup.
4040 - *
4041 - * Create database backup for the selected cPanel server.
4042 - *
4043 - * @param bool $ret_val Return output or not.
4044 - * @param int $website_id Website ID.
4045 - *
4046 - * @return mixed
4047 - */
4048 - public static function ajax_cpanel_action_create_database_backup( $ret_val = false, $website_id = null ) {
4000 + $payload = '/api/modules/wp-toolkit/v1/installations/' . $plesk_installation_id . '/backups?files%5B%5D=' . rawurlencode( $backup_name );
4049 4001
4050 - // Grab website_id & from Ajax post if $website_id is not set.
4051 - if ( empty( $website_id ) ) {
4002 + // Send Payload & create backup.
4003 + $api_response = static::call_plesk_api( 'DELETE', $payload, $plesk_baseurl, $plesk_api_key, $backup_data );
4052 4004
4053 - // Check nonce.
4054 - Api_Backups_Helper::security_nonce( 'cpanel_action_create_database_backup' );
4005 + $response_decoded = ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
4006 + $errors = ! empty( $response_decoded ) && ! empty( $response_decoded->task->errors ) ? $response_decoded->task->errors : '';
4055 4007
4056 - // Grab $_POST data.
4057 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4008 + // Return AJAX.
4009 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4010 + // Store Last Backup timestamp.
4011 + if ( empty( $errors ) && '204' === (string) $api_response['httpCode'] && 'true' === (string) $api_response['status'] ) {
4012 + wp_send_json( 'true' );
4013 + } else {
4014 + wp_die( esc_html( $errors ) );
4015 + }
4016 + }
4017 + }
4058 4018
4059 - }
4019 + /*********************************************************************************
4020 + * CPanel API Methods.
4021 + **********************************************************************************/
4022 + /**
4023 + * Call cPanel API, Authenticate & perform given method.
4024 + *
4025 + * @param string $method GET|POST|PUT|DELETE.
4026 + * @param string $url API endpoint for the call.
4027 + * @param string $baseurl Baseurl.
4028 + * @param string $username cPanel account username.
4029 + * @param string $password cPanel account password.
4030 + * @param mixed $backup_data Json encoded array - Optional post data for the call.
4031 + * @return array Output from cPanel API.
4032 + */
4033 + public static function call_cpanel_api( $method, $url, $baseurl, $username, $password, $backup_data = array() ) {
4060 4034
4061 - $post_data = array( 'mwp_action' => 'cpanel_mysqldump' );
4035 + // base64encode cPanel Username & Password.
4036 + $base64encoded = base64_encode( $username . ':' . $password ); //phpcs:ignore -- base64 encode.
4037 + $curl = curl_init();
4062 4038
4063 - $information = MainWP_Extensions_Handler::fetch_url_authed( $website_id, 'api_backups_mysqldump', $post_data );
4039 + curl_setopt_array(
4040 + $curl,
4041 + array(
4042 + CURLOPT_URL => $baseurl . $url,
4043 + CURLOPT_RETURNTRANSFER => true,
4044 + CURLOPT_ENCODING => '',
4045 + CURLOPT_MAXREDIRS => 10,
4046 + CURLOPT_TIMEOUT => 0,
4047 + CURLOPT_FOLLOWLOCATION => true,
4048 + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
4049 + CURLOPT_CUSTOMREQUEST => $method,
4050 + CURLOPT_POSTFIELDS => $backup_data,
4051 + CURLOPT_HTTPHEADER => array(
4052 + 'Content-Type: text/plain',
4053 + "Authorization: Basic $base64encoded",
4054 + ),
4055 + )
4056 + );
4064 4057
4065 - if ( $ret_val ) {
4066 - return $information;
4067 - }
4058 + $resp = curl_exec( $curl );
4068 4059
4069 - // Return AJAX.
4070 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4071 - // Store Last Backup timestamp.
4072 - if ( 'GOOD' === $information['result'] ) {
4073 - wp_send_json( 'true' );
4074 - } else {
4075 - wp_die( 'There was an issue while creating the database backup. Please check logs and try again.' );
4076 - }
4077 - }
4078 - }
4060 + $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
4061 + $response['httpCode'] = $httpCode;
4062 + $response['response'] = $resp;
4063 + if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
4064 + $response['status'] = 'false';
4065 + } else {
4066 + $response['status'] = 'true';
4067 + }
4068 + curl_close( $curl );
4069 + return $response;
4070 + }
4079 4071
4080 - /**
4081 - *
4082 - * CPanel: Action create manual backup.
4083 - *
4084 - * Create a cPanel Manual Backup.
4085 - *
4086 - * @param bool $ret_val Return output or not.
4087 - * @param int $website_id Website ID.
4088 - *
4089 - * @return mixed
4090 - */
4091 - public static function cpanel_action_create_manual_backup( $ret_val = false, $website_id = null ) {
4072 + /*********************************************************************************
4073 + * CPanel API Methods.
4074 + **********************************************************************************/
4075 + /**
4076 + * Call cPanel API, Authenticate & perform given method.
4077 + *
4078 + * @param string $method GET|POST|PUT|DELETE.
4079 + * @param string $url API endpoint for the call.
4080 + * @param string $baseurl base url.
4081 + * @param string $username cPanel account username.
4082 + * @param string $password cPanel account password.
4083 + * @param mixed $backup_data Json encoded array - Optional post data for the call.
4084 + * @return array Output from cPanel API.
4085 + */
4086 + public static function call_cpanel_api_json( $method, $url, $baseurl, $username, $password, $backup_data = array() ) {
4092 4087
4093 - // Authenticate cPanel account.
4094 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials( $website_id );
4095 - $website_id = $cpanel_authentication_credentials[0]['website_id'];
4088 + // base64encode cPanel Username & Password.
4089 + $base64encoded = base64_encode( $username . ':' . $password ); //phpcs:ignore -- base64 encode.
4090 + $curl = curl_init();
4096 4091
4097 - // Send Payload & create backup.
4098 - $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'] );
4099 - $response_decoded = is_array( $api_response ) && ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
4100 - $errors = ! empty( $response_decoded ) && is_object( $response_decoded ) && ! empty( $response_decoded->errors ) ? $response_decoded->errors['0'] : '';
4092 + curl_setopt_array(
4093 + $curl,
4094 + array(
4095 + CURLOPT_URL => $baseurl . $url,
4096 + CURLOPT_RETURNTRANSFER => true,
4097 + CURLOPT_ENCODING => '',
4098 + CURLOPT_MAXREDIRS => 10,
4099 + CURLOPT_TIMEOUT => 0,
4100 + CURLOPT_FOLLOWLOCATION => true,
4101 + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
4102 + CURLOPT_CUSTOMREQUEST => $method,
4103 + CURLOPT_POSTFIELDS => $backup_data,
4104 + CURLOPT_HTTPHEADER => array(
4105 + 'Accept: */*', // DO NOT REMOVE THIS LINE! Plesk API will DELETE ALL BACKUPS if this is not included!
4106 + 'Content-Type: application/json',
4107 + "Authorization: Basic $base64encoded",
4108 + ),
4109 + )
4110 + );
4101 4111
4102 - if ( empty( $errors ) ) {
4103 - // Save Timestamp.
4104 - $local_time = current_datetime();
4105 - $current_time = $local_time->getTimestamp() + $local_time->getOffset();
4106 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_last_backup', $current_time );
4107 - }
4112 + $resp = curl_exec( $curl );
4108 4113
4109 - $success = false;
4110 - if ( 'true' === $api_response['status'] ) {
4111 - $success = true;
4112 - }
4114 + $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
4115 + $response['httpCode'] = $httpCode;
4116 + $response['response'] = $resp;
4117 + if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
4118 + $response['status'] = 'false';
4119 + } else {
4120 + $response['status'] = 'true';
4121 + }
4122 + curl_close( $curl );
4123 + return $response;
4124 + }
4113 4125
4114 - if ( $ret_val ) {
4115 - return $api_response;
4116 - }
4126 + /**
4127 + *
4128 + * CPanel: Authentication.
4129 + *
4130 + * Grab needed authentication credentials for cPanel API - either from global settings or individual settings.
4131 + *
4132 + * @param int $website_id Website ID.
4133 + *
4134 + * @return array
4135 + */
4136 + public static function get_cpanel_authentication_credentials( $website_id = '' ) { //phpcs:ignore -- NOSONAR - complex.
4117 4137
4118 - // Return AJAX.
4119 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4120 - // Store Last Backup timestamp.
4121 - if ( empty( $errors ) ) {
4122 - wp_send_json( 'true' );
4123 - } else {
4124 - wp_die( esc_html( $errors ) );
4125 - }
4126 - }
4127 - }
4138 + $cpanel_authentication_credentials = array();
4128 4139
4129 - /**
4130 - *
4131 - * CPanel: Action create WP-Toolkit backup.
4132 - *
4133 - * Create a cPanel Manual Backup.
4134 - *
4135 - * @param bool $ret_val Return output or not.
4136 - *
4137 - * @return array|void
4138 - */
4139 - public static function cpanel_action_create_wptk_backup( $ret_val = false ) {
4140 + // Grab website_id & from Ajax post if $website_id is not set.
4141 + if ( empty( $website_id ) ) {
4142 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4143 + // Grab $_POST data.
4144 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4145 + } else {
4146 + // Grab $_GET['data'] from url if not Ajax call.
4147 + $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4148 + }
4149 + }
4140 4150
4141 - // Authenticate cPanel account.
4142 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
4143 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4144 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4145 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4146 - $website_id = $cpanel_authentication_credentials[0]['website_id'];
4151 + // Global / Individual check.
4152 + $global_individual_check = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_cpanel_individual' ) );
4153 + $mainwp_enable_cpanel_individual = isset( $global_individual_check['mainwp_enable_cpanel_individual'] ) ? $global_individual_check['mainwp_enable_cpanel_individual'] : '0';
4147 4154
4148 - // Grab Child Site options array.
4149 - $website = Api_Backups_Helper::get_website_by_id( $website_id );
4155 + if ( 'on' === $mainwp_enable_cpanel_individual ) {
4156 + // Grab cPanel baseurl, username & password.
4157 + $baseurl = Api_Backups_Helper::get_website_options( $website_id, array( 'cpanel_api_url' ) );
4158 + $cpanel_baseurl = isset( $baseurl['cpanel_api_url'] ) ? $baseurl['cpanel_api_url'] : null;
4150 4159
4151 - // Grab website url & trim trailing slash.
4152 - $website_url = trim( $website['url'], '/' );
4160 + // Grab cPanel username.
4161 + $username = Api_Backups_Helper::get_website_options( $website_id, array( 'cpanel_account_username' ) );
4162 + $cpanel_username = isset( $username['cpanel_account_username'] ) ? $username['cpanel_account_username'] : null;
4153 4163
4154 - // Grab list of WP Toolkit installations.
4155 - $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 );
4156 - $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4164 + // Grab cPanel password.
4165 + $cpanel_password = Api_Backups_Utility::get_instance()->get_child_api_key( $website_id, 'cpanel' );
4157 4166
4158 - if ( '201' !== $wp_toolkit_installation_list['httpCode'] && '200' !== $wp_toolkit_installation_list['httpCode'] && '204' !== $wp_toolkit_installation_list['httpCode'] ) {
4159 - $error = $wp_toolkit_installation_list_decoded->meta->message;
4160 - wp_die( esc_html( $error ) );
4161 - } elseif ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4162 - foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4163 - if ( $site->url === $website_url ) {
4164 - $wp_toolkit_installation_id = $site->id;
4165 - }
4166 - }
4167 - } else {
4168 - $wp_toolkit_installation_id = '';
4169 - }
4167 + // Grab cPanel site path.
4168 + $site_path = Api_Backups_Helper::get_website_options( $website_id, array( 'cpanel_site_path' ) );
4169 + $cpanel_site_path = isset( $site_path['cpanel_site_path'] ) ? $site_path['cpanel_site_path'] : null;
4170 4170
4171 - // Prepare Backup Payload.
4172 - $backup_data = array(
4173 - 'installationId' => $wp_toolkit_installation_id,
4174 - );
4175 - $backup_data = wp_json_encode( $backup_data );
4171 + } elseif ( '0' === $mainwp_enable_cpanel_individual ) {
4172 + // Grab cPanel baseurl, username & password.
4173 + $cpanel_baseurl = get_option( 'mainwp_cpanel_url' ); // Fixing when mergeing ???.
4174 + // Grab cPanel username.
4175 + $cpanel_username = get_option( 'mainwp_cpanel_account_username' ); // Fixing when mergeing ???.
4176 + // Grab cPanel password.
4177 + $cpanel_password = static::get_cpanel_account_password();
4176 4178
4177 - // Grab list of WP Toolkit installations.
4178 - $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 );
4179 - $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 + // Grab cPanel site path.
4180 + $cpanel_site_path = ( false === get_option( 'mainwp_cpanel_site_path' ) ) ? null : get_option( 'mainwp_cpanel_site_path' );
4181 + }
4180 4182
4181 - $error = '';
4182 - if ( '201' !== $wp_toolkit_backup_response['httpCode'] && '200' !== $wp_toolkit_backup_response['httpCode'] && '204' !== $wp_toolkit_backup_response['httpCode'] ) {
4183 - $error = ! empty( $wp_toolkit_backup_response_decoded ) && ! empty( $wp_toolkit_backup_response_decoded->meta->message ) ? $wp_toolkit_backup_response_decoded->meta->message : '';
4184 - } else {
4185 - // Save Timestamp.
4186 - $local_time = current_datetime();
4187 - $current_time = $local_time->getTimestamp() + $local_time->getOffset();
4188 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_last_backup', $current_time );
4189 - }
4183 + // Build array.
4184 + $cpanel_authentication_credentials[] = array(
4185 + 'cpanel_baseurl' => $cpanel_baseurl,
4186 + 'cpanel_username' => $cpanel_username,
4187 + 'cpanel_password' => $cpanel_password,
4188 + 'cpanel_site_path' => $cpanel_site_path,
4189 + 'website_id' => $website_id,
4190 + );
4190 4191
4191 - if ( $ret_val ) {
4192 - return $wp_toolkit_backup_response;
4193 - }
4192 + return $cpanel_authentication_credentials;
4193 + }
4194 4194
4195 - // Return AJAX.
4196 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4197 - // Store Last Backup timestamp.
4198 - if ( empty( $errors ) ) {
4199 - wp_send_json( 'true' );
4200 - } else {
4201 - wp_die( esc_html( $errors ) );
4202 - }
4203 - }
4204 - }
4195 + /**
4196 + *
4197 + * CPanel: Action get cPanel Home Directory.
4198 + *
4199 + * Grab cPanel Home Directory for manual backup links.
4200 + *
4201 + * @return string
4202 + */
4203 + public static function cpanel_action_get_home_directory() {
4205 4204
4206 - /**
4207 - *
4208 - * CPanel: Action create WP-Toolkit backup.
4209 - *
4210 - * Create a cPanel Manual Backup.
4211 - *
4212 - * @param bool $ret_val Return output or not.
4213 - *
4214 - * @return array|void
4215 - */
4216 - public static function cpanel_action_restore_wptk_backup( $ret_val = false ) {
4205 + // Authenticate cPanel account.
4206 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4207 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4208 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4209 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4217 4210
4218 - // Authenticate cPanel account.
4219 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
4220 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4221 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4222 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4223 - $website_id = $cpanel_authentication_credentials[0]['website_id'];
4211 + // Send Payload.
4212 + $api_response = static::call_cpanel_api( 'GET', '/execute/Variables/get_user_information', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4213 + $api_response_decoded = json_decode( $api_response['response'] );
4224 4214
4225 - // Grab Child Site options array.
4226 - $website = Api_Backups_Helper::get_website_by_id( $website_id );
4215 + if ( is_object( $api_response_decoded ) && isset( $api_response_decoded->data->home ) ) {
4216 + $cpanel_home_directory = $api_response_decoded->data->home;
4217 + } else {
4218 + $cpanel_home_directory = '';
4219 + }
4227 4220
4228 - // Grab website url & trim trailing slash.
4229 - $website_url = trim( $website['url'], '/' );
4221 + return $cpanel_home_directory;
4222 + }
4230 4223
4231 - // Grab list of WP Toolkit installations.
4232 - $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 );
4233 - $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4224 + /**
4225 + * Get cPanel manual account backups.
4226 + *
4227 + * @return false|string cPanel account backups
4228 + */
4229 + public static function get_cpanel_manual_account_backups() {
4234 4230
4235 - if ( '201' !== $wp_toolkit_installation_list['httpCode'] && '200' !== $wp_toolkit_installation_list['httpCode'] && '204' !== $wp_toolkit_installation_list['httpCode'] ) {
4236 - $error = $wp_toolkit_installation_list_decoded->meta->message;
4237 - wp_die( esc_html( $error ) );
4238 - } elseif ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4239 - foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4240 - if ( $site->url === $website_url ) {
4241 - $wp_toolkit_installation_id = $site->id;
4242 - }
4243 - }
4244 - } else {
4245 - $wp_toolkit_installation_id = '';
4246 - }
4231 + // Define array for Manual Backups.
4232 + $manual_backups = array();
4247 4233
4248 - // Prepare Backup Payload.
4249 - $backup_data = array(
4250 - 'installationId' => $wp_toolkit_installation_id,
4251 - 'fileName' => isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : '', //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4252 - 'clobber' => false,
4253 - 'dropAllDatabaseTables' => false,
4234 + // Authenticate cPanel account.
4235 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4236 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4237 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4238 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4254 4239
4255 - );
4256 - $backup_data = wp_json_encode( $backup_data );
4240 + // Send Payload.
4241 + $api_response = static::call_cpanel_api( 'GET', '/execute/Fileman/list_files?dir=/&include_mime=1&types=file', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4242 + $api_response_decoded = json_decode( $api_response['response'] );
4257 4243
4258 - // Grab list of WP Toolkit installations.
4259 - $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 );
4260 - $wp_toolkit_backup_response_decoded = json_decode( $wp_toolkit_backup_response['response'] );
4244 + // Build list.
4245 + if ( is_object( $api_response_decoded ) && isset( $api_response_decoded->data ) ) {
4246 + $files = $api_response_decoded->data;
4247 + foreach ( $files as $file ) {
4248 + if ( 'application/x-gzip' === $file->rawmimetype ) {
4249 + $manual_backups[] = array(
4250 + 'file_name' => $file->file,
4251 + 'absolute_dir' => $file->absdir,
4252 + 'timestamp' => $file->ctime,
4253 + );
4254 + }
4255 + }
4256 + } else {
4257 + $manual_backups = array();
4258 + }
4261 4259
4262 - if ( '201' !== $wp_toolkit_backup_response['httpCode'] && '200' !== $wp_toolkit_backup_response['httpCode'] && '204' !== $wp_toolkit_backup_response['httpCode'] ) {
4263 - $error = $wp_toolkit_backup_response_decoded->meta->message;
4264 - wp_die( esc_html( $error ) );
4265 - } else {
4266 - wp_send_json( 'true' );
4267 - }
4260 + // return array of Manual Backups.
4261 + return wp_json_encode( $manual_backups );
4262 + }
4268 4263
4269 - if ( $ret_val ) {
4270 - return $wp_toolkit_backup_response;
4271 - }
4272 - }
4264 + /**
4265 + * Get cPanel manual database backups.
4266 + *
4267 + * Create manual database backup via mysqldump.
4268 + * Backups will be stored within `/uploads/mainwp/api_db_backups` directory.
4269 + *
4270 + * @param int $website_id Website ID.
4271 + *
4272 + * @return false|string cPanel account backups
4273 + */
4274 + public static function get_cpanel_manual_database_backups( $website_id = '' ) {
4273 4275
4274 - /**
4275 - *
4276 - * Plesk: Action delete backup.
4277 - *
4278 - * Delete Plesk Backup.
4279 - *
4280 - * @return void
4281 - */
4282 - public static function cpanel_action_delete_wptk_backup() {
4276 + unset( $website_id );
4283 4277
4284 - // Grab website_id & backup_api name from Ajax post.
4285 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4286 - // Grab $_POST data.
4287 - $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
4288 - $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4289 - }
4278 + // Define array for Manual Backups.
4279 + $manual_backups = array();
4290 4280
4291 - // Authenticate cPanel account.
4292 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
4293 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4294 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4295 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4281 + // Authenticate cPanel account.
4282 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4283 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4284 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4285 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4296 4286
4297 - // Grab Child Site options array.
4298 - $website = Api_Backups_Helper::get_website_by_id( $website_id );
4287 + // Grab cPanel site path.
4288 + $cpanel_db_backups_path = $cpanel_authentication_credentials[0]['cpanel_site_path'] . '/wp-content/uploads/mainwp/api_db_backups';
4299 4289
4300 - // Grab website url & trim trailing slash.
4301 - $website_url = trim( $website['url'], '/' );
4290 + // Send Payload.
4291 + $api_response = static::call_cpanel_api( 'GET', '/execute/Fileman/list_files?dir=' . $cpanel_db_backups_path . '&include_mime=1&types=file', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4292 + $api_response_decoded = json_decode( $api_response['response'] );
4302 4293
4303 - $wp_toolkit_installation_id = '';
4294 + // Build list.
4295 + if ( is_object( $api_response_decoded ) && isset( $api_response_decoded->data ) ) {
4296 + $files = $api_response_decoded->data;
4297 + foreach ( $files as $file ) {
4298 + if ( 'application/x-gzip' === $file->rawmimetype ) {
4299 + $manual_backups[] = array(
4300 + 'file_name' => $file->file,
4301 + 'absolute_dir' => $file->absdir,
4302 + 'timestamp' => $file->ctime,
4303 + );
4304 + }
4305 + }
4306 + } else {
4307 + $manual_backups = array();
4308 + }
4304 4309
4305 - // Grab list of WP Toolkit installations.
4306 - $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 );
4307 - $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4310 + // return array of Manual Backups.
4311 + return wp_json_encode( $manual_backups );
4312 + }
4308 4313
4309 - if ( '201' !== $wp_toolkit_installation_list['httpCode'] && '200' !== $wp_toolkit_installation_list['httpCode'] && '204' !== $wp_toolkit_installation_list['httpCode'] ) {
4310 - $error = $wp_toolkit_installation_list_decoded->meta->message;
4311 - wp_die( esc_html( $error ) );
4312 - } elseif ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4313 - foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4314 - if ( $site->url === $website_url ) {
4315 - $wp_toolkit_installation_id = $site->id;
4316 - }
4317 - }
4318 - }
4314 + /**
4315 + *
4316 + * Method get_3rdparty_installation_path().
4317 + *
4318 + * @param string $what what to get path.
4319 + *
4320 + * @return string api path.
4321 + */
4322 + public static function get_3rdparty_installation_path( $what = '' ) {
4323 + $path = '/3rdparty/wpt/index.php/v1/installations/';
4324 + if ( 'with_sort' === $what ) {
4325 + $path .= '?sortBy=title&sortOrder=asc';
4326 + }
4327 + return $path;
4328 + }
4319 4329
4320 - $backup_data = wp_json_encode(
4321 - array(
4322 - 'delete' => true,
4323 - )
4324 - );
4330 + /**
4331 + *
4332 + * CPanel: Action refresh available WP-Toolit backups.
4333 + *
4334 + * Save backups to DB for the selected server.
4335 + *
4336 + * @param int $website_id Website id.
4337 + *
4338 + * @return array
4339 + */
4340 + public function get_cpanel_wp_toolkit_backups( $website_id ) {
4325 4341
4326 - /**
4327 - * Payload for deleting a backup.
4328 - * plesk_baseurl must include the port number.
4329 - * https://{plesk_baseurl:8443}/api/modules/wp-toolkit/v1/installations/{plesk_installation_id}/backups?files%5B%5D={backup_name}
4330 - * Backup Name Example ( must be urlencoded ): sweet-lovelace.104-207-132-143.plesk.page_site-1__2024-01-12T16_37_25%2B0000.zip
4331 - *
4332 - * /v1/installations/{installationId}/backups
4333 - */
4334 - $payload = '/3rdparty/wpt/index.php/v1/installations/' . $wp_toolkit_installation_id . '/backups?files%5B%5D=' . rawurlencode( $backup_name );
4342 + // Grab Child Site options array.
4343 + $website = Api_Backups_Helper::get_website_by_id( $website_id );
4335 4344
4336 - // Send Payload & create backup.
4337 - $api_response = self::call_cpanel_api_json( 'DELETE', $payload, $cpanel_baseurl, $cpanel_username, $cpanel_password, $backup_data );
4338 - $response_decoded = json_decode( $api_response['response'] );
4339 - $errors = $response_decoded->task->errors;
4345 + // Grab website url & trim trailing slash.
4346 + $website_url = trim( $website['url'], '/' );
4340 4347
4341 - // Return AJAX.
4342 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4343 - // Store Last Backup timestamp.
4344 - if ( empty( $errors ) && '204' === (string) $api_response['httpCode'] && 'true' === (string) $api_response['status'] ) {
4345 - wp_send_json( 'true' );
4346 - } else {
4347 - wp_die( esc_html( $errors ) );
4348 - }
4349 - }
4350 - }
4348 + // Authenticate cPanel account.
4349 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4350 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4351 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4352 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4351 4353
4352 - /**
4353 - *
4354 - * CPanel: Action refresh available backups.
4355 - *
4356 - * Save backups to DB for the selected cPanel server.
4357 - *
4358 - * @return void
4359 - */
4360 - public function cpanel_action_refresh_available_backups() {
4354 + $wp_toolkit_installation_id = '';
4361 4355
4362 - // Authenticate cPanel account.
4363 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
4364 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4365 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4366 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4367 - $cpanel_site_path = $cpanel_authentication_credentials[0]['cpanel_site_path'];
4368 - $website_id = $cpanel_authentication_credentials[0]['website_id'];
4356 + // Grab list of WP Toolkit installations.
4357 + $wp_toolkit_installation_list = static::call_cpanel_api( 'GET', $this->get_3rdparty_installation_path( 'with_sort' ), $cpanel_baseurl, $cpanel_username, $cpanel_password );
4358 + $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4369 4359
4370 - // Grab automatic WHM backups.
4371 - $api_response = self::call_cpanel_api( 'GET', '/execute/Restore/query_file_info?path=' . $cpanel_site_path . '&exists=1', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4372 - $all_backups = $api_response['response'];
4360 + // Search for website url in list of WP Toolkit installations & grab Site ID.
4361 + if ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4362 + foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4363 + if ( $site->url === $website_url ) {
4364 + $wp_toolkit_installation_id = $site->id;
4365 + }
4366 + }
4367 + }
4373 4368
4374 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_available_backups', $all_backups );
4375 - Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'cpanel_auto' );
4369 + // Grab backup meta for found Site ID.
4370 + $wp_toolkit_backups = static::call_cpanel_api( 'GET', static::get_3rdparty_installation_path() . $wp_toolkit_installation_id . '/backups/meta', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4371 + if ( 'true' === $wp_toolkit_backups['status'] ) {
4372 + return $wp_toolkit_backups['response'];
4373 + } else {
4374 + return array();
4375 + }
4376 + }
4376 4377
4377 - // Grab manual account backups.
4378 - $manual_backups = self::get_cpanel_manual_account_backups();
4379 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_manual_backups', $manual_backups );
4378 + /**
4379 + * CPanel: action restore backup.
4380 + *
4381 + * Restore cPanel backup for the selected cPanel server.
4382 + *
4383 + * @return void
4384 + */
4385 + public function ajax_cpanel_action_restore_backup() {
4386 + Api_Backups_Helper::security_nonce( 'cpanel_action_restore_backup' );
4387 + static::cpanel_action_restore_backup();
4388 + die();
4389 + }
4380 4390
4381 - Api_Backups_Utility::save_lasttime_backup( $website_id, $manual_backups, 'cpanel_manual' );
4391 + /**
4392 + * CPanel: action restore database backup.
4393 + *
4394 + * Restore cPanel backup for the selected cPanel server.
4395 + *
4396 + * @return void
4397 + */
4398 + public function ajax_cpanel_action_restore_database_backup() {
4399 + Api_Backups_Helper::security_nonce( 'cpanel_action_restore_database_backup' );
4400 + static::cpanel_action_restore_database_backup();
4401 + die();
4402 + }
4382 4403
4383 - // Grab manual DB backups.
4384 - $database_backups = self::get_cpanel_manual_database_backups( $website_id );
4385 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_manual_database_backups', $database_backups );
4404 + /**
4405 + * CPanel: action restore manual backup.
4406 + *
4407 + * Restore cPanel backup for the selected cPanel server.
4408 + *
4409 + * @return void
4410 + */
4411 + public function ajax_cpanel_action_restore_manual_backup() {
4412 + Api_Backups_Helper::security_nonce( 'cpanel_action_restore_manual_backup' );
4413 + static::cpanel_action_restore_manual_backup();
4414 + die();
4415 + }
4386 4416
4387 - // Grab WP-Toolkit backups.
4388 - $wp_toolkit_enabled = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_wp_toolkit' ) );
4389 - $wp_toolkit_enabled = isset( $wp_toolkit_enabled['mainwp_enable_wp_toolkit'] ) ? strtolower( $wp_toolkit_enabled['mainwp_enable_wp_toolkit'] ) : 0;
4390 - if ( $wp_toolkit_enabled ) {
4391 - $wp_toolkit_backups = self::get_cpanel_wp_toolkit_backups( $website_id );
4392 - if ( $wp_toolkit_backups ) {
4393 - Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_wp_toolkit_backups', $wp_toolkit_backups );
4394 - Api_Backups_Utility::save_lasttime_backup( $website_id, $wp_toolkit_backups, 'cpanel_wp_toolkit' );
4395 - }
4396 - }
4417 + /**
4418 + * CPanel: action refresh available backups.
4419 + *
4420 + * Refresh available backups for the selected cPanel server.
4421 + *
4422 + * @return void
4423 + */
4424 + public function ajax_cpanel_action_refresh_available_backups() {
4425 + Api_Backups_Helper::security_nonce( 'cpanel_action_refresh_available_backups' );
4426 + static::cpanel_action_refresh_available_backups();
4427 + die();
4428 + }
4397 4429
4398 - // Return AJAX.
4399 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4400 - // Store Last Backup timestamp.
4401 - if ( 'true' === $api_response['status'] ) {
4402 - wp_send_json( 'true' );
4403 - } else {
4404 - wp_die( 'false' );
4405 - }
4406 - }
4407 - }
4430 + /**
4431 + * CPanel: action create backup.
4432 + *
4433 + * Create backup for the selected cPanel server.
4434 + *
4435 + * @return void
4436 + */
4437 + public function ajax_cpanel_action_create_manual_backup() {
4438 + Api_Backups_Helper::security_nonce( 'cpanel_action_create_manual_backup' );
4439 + static::cpanel_action_create_manual_backup();
4440 + die();
4441 + }
4408 4442
4409 - /**
4410 - *
4411 - * CPanel: Action restore selected backup.
4412 - *
4413 - * @return void
4414 - */
4415 - public function cpanel_action_restore_backup() {
4443 + /**
4444 + * CPanel: action create WP-Toolkit backup.
4445 + *
4446 + * Create backup for the selected cPanel server.
4447 + *
4448 + * @return void
4449 + */
4450 + public function ajax_cpanel_action_create_wptk_backup() {
4451 + Api_Backups_Helper::security_nonce( 'cpanel_action_create_wptk_backup' );
4452 + static::cpanel_action_create_wptk_backup();
4453 + die();
4454 + }
4416 4455
4417 - Api_Backups_Helper::security_nonce( 'cpanel_action_restore_backup' );
4456 + /**
4457 + * CPanel: action create WP-Toolkit backup.
4458 + *
4459 + * Create backup for the selected cPanel server.
4460 + *
4461 + * @return void
4462 + */
4463 + public function ajax_cpanel_action_restore_wptk_backup() {
4464 + Api_Backups_Helper::security_nonce( 'cpanel_action_restore_wptk_backup' );
4465 + static::cpanel_action_restore_wptk_backup();
4466 + die();
4467 + }
4418 4468
4419 - // Authenticate cPanel account.
4420 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
4421 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4422 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4423 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4424 - $cpanel_site_path = $cpanel_authentication_credentials[0]['cpanel_site_path'];
4425 - $website_id = $cpanel_authentication_credentials[0]['website_id'];
4469 + /**
4470 + * CPanel: action delete WP-Toolkit backup.
4471 + *
4472 + * Create backup for the selected cPanel server.
4473 + *
4474 + * @return void
4475 + */
4476 + public function ajax_cpanel_action_delete_wptk_backup() {
4477 + Api_Backups_Helper::security_nonce( 'cpanel_action_delete_wptk_backup' );
4478 + static::cpanel_action_delete_wptk_backup();
4479 + die();
4480 + }
4426 4481
4427 - // Grab website_id & backup_api name from Ajax post.
4428 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4429 - // Grab $_POST data.
4430 - $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
4431 - }
4482 + /**
4483 + * CPanel: action create full backup.
4484 + *
4485 + * Create backup for the selected cPanel server.
4486 + *
4487 + * @return void
4488 + */
4489 + public static function ajax_cpanel_action_create_full_backup() { //phpcs:ignore -- NOSONAR - complex.
4490 + Api_Backups_Helper::security_nonce( 'cpanel_action_create_full_backup' );
4432 4491
4433 - // Send Payload & create backup.
4434 - $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 );
4492 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4493 + // Grab Child Site ID from $_POST data.
4494 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4435 4495
4436 - // Return AJAX.
4437 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4438 - // Store Last Backup timestamp.
4439 - if ( '200' === (string) $api_response['httpCode'] ) {
4440 - wp_send_json( 'true' );
4441 - } else {
4442 - wp_die( 'false' );
4443 - }
4444 - }
4445 - }
4496 + $opts = Api_Backups_Helper::get_website_options(
4497 + $website_id,
4498 + array(
4499 + 'mainwp_enable_wp_toolkit',
4500 + )
4501 + );
4446 4502
4447 - /**
4448 - *
4449 - * CPanel: Action restore selected database backup.
4450 - *
4451 - * @return void
4452 - */
4453 - public function cpanel_action_restore_database_backup() {
4503 + $mainwp_enable_wp_toolkit = '';
4454 4504
4455 - // Authenticate cPanel account.
4456 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
4505 + if ( is_array( $opts ) ) {
4506 + $mainwp_enable_wp_toolkit = $opts['mainwp_enable_wp_toolkit'] ?? '0';
4507 + }
4457 4508
4458 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4459 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4460 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4461 - $cpanel_site_path = $cpanel_authentication_credentials[0]['cpanel_site_path'];
4462 - $website_id = $cpanel_authentication_credentials[0]['website_id'];
4509 + // Create file backup.
4510 + $file_backup_response = static::cpanel_action_create_manual_backup( true );
4511 + $response_decoded = json_decode( $file_backup_response['response'] );
4512 + $errors = $response_decoded->errors['0'];
4463 4513
4464 - // Grab website_id & backup_api name from Ajax post.
4465 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4466 - // Grab $_POST data.
4467 - $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
4468 - $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
4469 - }
4514 + // If no errors with file backup, create database backup.
4515 + if ( empty( $errors ) ) {
4470 4516
4471 - $backup_full_path = $backup_path . '/' . $backup_id;
4517 + // If no errors, create database backup.
4518 + $database_backup_response = static::ajax_cpanel_action_create_database_backup( true, $website_id );
4472 4519
4473 - // Send Payload & create backup. https://{host}:{port}/execute/Backup/restore_databases?backup=database_file_name.sql.gz.
4474 - $api_response = self::call_cpanel_api( 'POST', '/execute/Backup/restore_databases?backup=' . $backup_full_path, $cpanel_baseurl, $cpanel_username, $cpanel_password );
4475 - // Return AJAX.
4476 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4477 - // Store Last Backup timestamp.
4478 - if ( '200' === (string) $api_response['httpCode'] ) {
4479 - wp_send_json( 'true' );
4480 - } else {
4481 - wp_die( 'false' );
4482 - }
4483 - }
4484 - }
4520 + // If no errors, & WP-Toolikit is enabled create WP-Toolkit backup or return true.
4521 + if ( 'GOOD' === $database_backup_response['result'] ) {
4522 + // If WP Toolkit is enabled, create WP Toolkit backup.
4523 + if ( 'on' === $mainwp_enable_wp_toolkit ) {
4524 + $cpanel_wptk_backup_response = static::cpanel_action_create_wptk_backup( true );
4525 + if ( '201' !== $cpanel_wptk_backup_response['httpCode'] && '200' !== $cpanel_wptk_backup_response['httpCode'] && '204' !== $cpanel_wptk_backup_response['httpCode'] ) {
4526 + wp_die( 'There was an issue while creating the Database backup. Please check logs and try again.' );
4527 + } else {
4528 + // Return true for WP-Toolkit backup.
4529 + wp_send_json( 'true' );
4530 + }
4531 + } else {
4532 + // Return true for cPanel backup.
4533 + wp_send_json( 'true' );
4534 + }
4535 + } else {
4536 + // Return error for cPanel database backup.
4537 + wp_die( 'There was an issue while creating the Cpanel Database backup. Please check logs and try again.' );
4538 + }
4539 + } else {
4540 + // If cpanel file backup errors, return false.
4541 + wp_die( esc_html( $errors ) );
4542 + }
4543 + }
4544 + }
4485 4545
4486 - /**
4487 - *
4488 - * CPanel: Action restore selected manual backup.
4489 - *
4490 - * @return void
4491 - */
4492 - public function cpanel_action_restore_manual_backup() {
4546 + /**
4547 + * CPanel: action create database backup.
4548 + *
4549 + * Create database backup for the selected cPanel server.
4550 + *
4551 + * @param bool $ret_val Return output or not.
4552 + * @param int $website_id Website ID.
4553 + *
4554 + * @return mixed
4555 + */
4556 + public static function ajax_cpanel_action_create_database_backup( $ret_val = false, $website_id = null ) {
4493 4557
4494 - // Authenticate cPanel account.
4495 - $cpanel_authentication_credentials = self::get_cpanel_authentication_credentials();
4558 + // Grab website_id & from Ajax post if $website_id is not set.
4559 + if ( empty( $website_id ) ) {
4496 4560
4497 - $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4498 - $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4499 - $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4500 - $cpanel_site_path = $cpanel_authentication_credentials[0]['cpanel_site_path'];
4501 - $website_id = $cpanel_authentication_credentials[0]['website_id'];
4561 + // Check nonce.
4562 + Api_Backups_Helper::security_nonce( 'cpanel_action_create_database_backup' );
4502 4563
4503 - // Grab website_id & backup_api name from Ajax post.
4504 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4505 - // Grab $_POST data.
4506 - $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
4507 - $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
4508 - }
4564 + // Grab $_POST data.
4565 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4509 4566
4510 - /**
4511 - * Output example for api call.:
4512 - * Endpoint: /execute/Backup/restore_files
4513 - * Backup file: backup-1.4.2024_17-45-59_cpanel-user.tar.gz
4514 - * Backup directory: /home/{cpanel-user}
4515 - * Backup full path: /home/{cpanel-user}/backup-1.4.2024_17-45-59_cpanel-user.tar.gz
4516 - *
4517 - * 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}.
4518 - */
4519 - $backup_full_path = $backup_path . '/' . $backup_id;
4520 - $directory = $backup_path;
4567 + }
4521 4568
4522 - // Send Payload & create backup.
4523 - $api_response = self::call_cpanel_api( 'POST', '/execute/Backup/restore_files?backup=' . $backup_full_path . '&directory=' . $directory, $cpanel_baseurl, $cpanel_username, $cpanel_password );
4524 - $response_decoded = json_decode( $api_response['response'] );
4525 - $errors = $response_decoded->errors['0'];
4569 + $post_data = array( 'mwp_action' => 'cpanel_mysqldump' );
4526 4570
4527 - // Return AJAX.
4528 - if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4529 - // Store Last Backup timestamp.
4530 - if ( '200' === (string) $api_response['httpCode'] && empty( $errors ) ) {
4531 - wp_send_json( 'true' );
4532 - } else {
4533 - wp_die( 'false' );
4534 - }
4535 - }
4536 - }
4571 + $information = MainWP_Extensions_Handler::fetch_url_authed( $website_id, 'api_backups_mysqldump', $post_data );
4537 4572
4538 - // END class MainWP_3rdParty_Backup.
4573 + if ( $ret_val ) {
4574 + return $information;
4575 + }
4576 +
4577 + // Return AJAX.
4578 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4579 + // Store Last Backup timestamp.
4580 + if ( 'GOOD' === $information['result'] ) {
4581 + wp_send_json( 'true' );
4582 + } else {
4583 + wp_die( 'There was an issue while creating the database backup. Please check logs and try again.' );
4584 + }
4585 + }
4586 + }
4587 +
4588 + /**
4589 + *
4590 + * CPanel: Action create manual backup.
4591 + *
4592 + * Create a cPanel Manual Backup.
4593 + *
4594 + * @param bool $ret_val Return output or not.
4595 + * @param int $website_id Website ID.
4596 + *
4597 + * @return mixed
4598 + */
4599 + public static function cpanel_action_create_manual_backup( $ret_val = false, $website_id = null ) {
4600 +
4601 + // Authenticate cPanel account.
4602 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials( $website_id );
4603 + $website_id = $cpanel_authentication_credentials[0]['website_id'];
4604 +
4605 + // Send Payload & create backup.
4606 + $api_response = static::call_cpanel_api( 'GET', '/execute/Backup/fullbackup_to_homedir', $cpanel_authentication_credentials[0]['cpanel_baseurl'], $cpanel_authentication_credentials[0]['cpanel_username'], $cpanel_authentication_credentials[0]['cpanel_password'] );
4607 + $response_decoded = is_array( $api_response ) && ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
4608 + $errors = ! empty( $response_decoded ) && is_object( $response_decoded ) && ! empty( $response_decoded->errors ) ? $response_decoded->errors['0'] : '';
4609 +
4610 + if ( empty( $errors ) ) {
4611 + // Save Timestamp.
4612 + $local_time = current_datetime();
4613 + $current_time = $local_time->getTimestamp() + $local_time->getOffset();
4614 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_last_backup', $current_time );
4615 + }
4616 +
4617 + if ( $ret_val ) {
4618 + return $api_response;
4619 + }
4620 +
4621 + // Return AJAX.
4622 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4623 + // Store Last Backup timestamp.
4624 + if ( empty( $errors ) ) {
4625 + wp_send_json( 'true' );
4626 + } else {
4627 + wp_die( esc_html( $errors ) );
4628 + }
4629 + }
4630 + }
4631 +
4632 + /**
4633 + *
4634 + * CPanel: Action create WP-Toolkit backup.
4635 + *
4636 + * Create a cPanel Manual Backup.
4637 + *
4638 + * @param bool $ret_val Return output or not.
4639 + *
4640 + * @return array|void
4641 + */
4642 + public static function cpanel_action_create_wptk_backup( $ret_val = false ) { //phpcs:ignore -- NOSONAR - complex.
4643 +
4644 + // Authenticate cPanel account.
4645 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4646 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4647 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4648 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4649 + $website_id = $cpanel_authentication_credentials[0]['website_id'];
4650 +
4651 + // Grab Child Site options array.
4652 + $website = Api_Backups_Helper::get_website_by_id( $website_id );
4653 +
4654 + // Grab website url & trim trailing slash.
4655 + $website_url = trim( $website['url'], '/' );
4656 +
4657 + // Grab list of WP Toolkit installations.
4658 + $wp_toolkit_installation_list = static::call_cpanel_api( 'GET', static::get_3rdparty_installation_path( 'with_sort' ), $cpanel_baseurl, $cpanel_username, $cpanel_password );
4659 + $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4660 +
4661 + if ( '201' !== $wp_toolkit_installation_list['httpCode'] && '200' !== $wp_toolkit_installation_list['httpCode'] && '204' !== $wp_toolkit_installation_list['httpCode'] ) {
4662 + $error = $wp_toolkit_installation_list_decoded->meta->message;
4663 + wp_die( esc_html( $error ) );
4664 + } elseif ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4665 + foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4666 + if ( $site->url === $website_url ) {
4667 + $wp_toolkit_installation_id = $site->id;
4668 + }
4669 + }
4670 + } else {
4671 + $wp_toolkit_installation_id = '';
4672 + }
4673 +
4674 + // Prepare Backup Payload.
4675 + $backup_data = array(
4676 + 'installationId' => $wp_toolkit_installation_id,
4677 + );
4678 + $backup_data = wp_json_encode( $backup_data );
4679 +
4680 + // Grab list of WP Toolkit installations.
4681 + $wp_toolkit_backup_response = static::call_cpanel_api_json( 'POST', '/3rdparty/wpt/index.php/v1/features/backups/creator', $cpanel_baseurl, $cpanel_username, $cpanel_password, $backup_data );
4682 + $wp_toolkit_backup_response_decoded = is_array( $wp_toolkit_backup_response ) && ! empty( $wp_toolkit_backup_response['response'] ) ? json_decode( $wp_toolkit_backup_response['response'] ) : '';
4683 +
4684 + $errors = '';
4685 + if ( '201' !== $wp_toolkit_backup_response['httpCode'] && '200' !== $wp_toolkit_backup_response['httpCode'] && '204' !== $wp_toolkit_backup_response['httpCode'] ) {
4686 + $errors = ! empty( $wp_toolkit_backup_response_decoded ) && ! empty( $wp_toolkit_backup_response_decoded->meta->message ) ? $wp_toolkit_backup_response_decoded->meta->message : '';
4687 + } else {
4688 + // Save Timestamp.
4689 + $local_time = current_datetime();
4690 + $current_time = $local_time->getTimestamp() + $local_time->getOffset();
4691 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_last_backup', $current_time );
4692 + }
4693 +
4694 + if ( $ret_val ) {
4695 + return $wp_toolkit_backup_response;
4696 + }
4697 +
4698 + // Return AJAX.
4699 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4700 + // Store Last Backup timestamp.
4701 + if ( empty( $errors ) ) {
4702 + wp_send_json( 'true' );
4703 + } else {
4704 + wp_die( esc_html( $errors ) );
4705 + }
4706 + }
4707 + }
4708 +
4709 + /**
4710 + *
4711 + * CPanel: Action create WP-Toolkit backup.
4712 + *
4713 + * Create a cPanel Manual Backup.
4714 + *
4715 + * @param bool $ret_val Return output or not.
4716 + *
4717 + * @return array|void
4718 + */
4719 + public static function cpanel_action_restore_wptk_backup( $ret_val = false ) {
4720 +
4721 + // Authenticate cPanel account.
4722 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4723 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4724 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4725 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4726 + $website_id = $cpanel_authentication_credentials[0]['website_id'];
4727 +
4728 + // Grab Child Site options array.
4729 + $website = Api_Backups_Helper::get_website_by_id( $website_id );
4730 +
4731 + // Grab website url & trim trailing slash.
4732 + $website_url = trim( $website['url'], '/' );
4733 +
4734 + // Grab list of WP Toolkit installations.
4735 + $wp_toolkit_installation_list = static::call_cpanel_api( 'GET', static::get_3rdparty_installation_path( 'with_sort' ), $cpanel_baseurl, $cpanel_username, $cpanel_password );
4736 + $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4737 +
4738 + if ( '201' !== $wp_toolkit_installation_list['httpCode'] && '200' !== $wp_toolkit_installation_list['httpCode'] && '204' !== $wp_toolkit_installation_list['httpCode'] ) {
4739 + $error = $wp_toolkit_installation_list_decoded->meta->message;
4740 + wp_die( esc_html( $error ) );
4741 + } elseif ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4742 + foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4743 + if ( $site->url === $website_url ) {
4744 + $wp_toolkit_installation_id = $site->id;
4745 + }
4746 + }
4747 + } else {
4748 + $wp_toolkit_installation_id = '';
4749 + }
4750 +
4751 + // Prepare Backup Payload.
4752 + $backup_data = array(
4753 + 'installationId' => $wp_toolkit_installation_id,
4754 + 'fileName' => isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : '', //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4755 + 'clobber' => false,
4756 + 'dropAllDatabaseTables' => false,
4757 +
4758 + );
4759 + $backup_data = wp_json_encode( $backup_data );
4760 +
4761 + // Grab list of WP Toolkit installations.
4762 + $wp_toolkit_backup_response = static::call_cpanel_api_json( 'POST', '/3rdparty/wpt/index.php/v1/features/backups/restorer', $cpanel_baseurl, $cpanel_username, $cpanel_password, $backup_data );
4763 + $wp_toolkit_backup_response_decoded = json_decode( $wp_toolkit_backup_response['response'] );
4764 +
4765 + if ( '201' !== $wp_toolkit_backup_response['httpCode'] && '200' !== $wp_toolkit_backup_response['httpCode'] && '204' !== $wp_toolkit_backup_response['httpCode'] ) {
4766 + $error = $wp_toolkit_backup_response_decoded->meta->message;
4767 + wp_die( esc_html( $error ) );
4768 + } else {
4769 + wp_send_json( 'true' );
4770 + }
4771 +
4772 + if ( $ret_val ) {
4773 + return $wp_toolkit_backup_response;
4774 + }
4775 + }
4776 +
4777 + /**
4778 + *
4779 + * Plesk: Action delete backup.
4780 + *
4781 + * Delete Plesk Backup.
4782 + *
4783 + * @return void
4784 + */
4785 + public static function cpanel_action_delete_wptk_backup() { //phpcs:ignore -- NOSONAR - complex.
4786 +
4787 + // Grab website_id & backup_api name from Ajax post.
4788 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4789 + // Grab $_POST data.
4790 + $backup_name = isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4791 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4792 + }
4793 +
4794 + // Authenticate cPanel account.
4795 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4796 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4797 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4798 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4799 +
4800 + // Grab Child Site options array.
4801 + $website = Api_Backups_Helper::get_website_by_id( $website_id );
4802 +
4803 + // Grab website url & trim trailing slash.
4804 + $website_url = trim( $website['url'], '/' );
4805 +
4806 + $wp_toolkit_installation_id = '';
4807 +
4808 + // Grab list of WP Toolkit installations.
4809 + $wp_toolkit_installation_list = static::call_cpanel_api( 'GET', static::get_3rdparty_installation_path( 'with_sort' ), $cpanel_baseurl, $cpanel_username, $cpanel_password );
4810 + $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4811 +
4812 + if ( '201' !== $wp_toolkit_installation_list['httpCode'] && '200' !== $wp_toolkit_installation_list['httpCode'] && '204' !== $wp_toolkit_installation_list['httpCode'] ) {
4813 + $error = $wp_toolkit_installation_list_decoded->meta->message;
4814 + wp_die( esc_html( $error ) );
4815 + } elseif ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4816 + foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4817 + if ( $site->url === $website_url ) {
4818 + $wp_toolkit_installation_id = $site->id;
4819 + }
4820 + }
4821 + }
4822 +
4823 + $backup_data = wp_json_encode(
4824 + array(
4825 + 'delete' => true,
4826 + )
4827 + );
4828 +
4829 + /**
4830 + * Payload for deleting a backup.
4831 + * plesk_baseurl must include the port number.
4832 + * https://{plesk_baseurl:8443}/api/modules/wp-toolkit/v1/installations/{plesk_installation_id}/backups?files%5B%5D={backup_name}
4833 + * Backup Name Example ( must be urlencoded ): sweet-lovelace.104-207-132-143.plesk.page_site-1__2024-01-12T16_37_25%2B0000.zip
4834 + *
4835 + * /v1/installations/{installationId}/backups
4836 + */
4837 + $payload = static::get_3rdparty_installation_path() . $wp_toolkit_installation_id . '/backups?files%5B%5D=' . rawurlencode( $backup_name );
4838 +
4839 + // Send Payload & create backup.
4840 + $api_response = static::call_cpanel_api_json( 'DELETE', $payload, $cpanel_baseurl, $cpanel_username, $cpanel_password, $backup_data );
4841 + $response_decoded = json_decode( $api_response['response'] );
4842 + $errors = $response_decoded->task->errors;
4843 +
4844 + // Return AJAX.
4845 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4846 + // Store Last Backup timestamp.
4847 + if ( empty( $errors ) && '204' === (string) $api_response['httpCode'] && 'true' === (string) $api_response['status'] ) {
4848 + wp_send_json( 'true' );
4849 + } else {
4850 + wp_die( esc_html( $errors ) );
4851 + }
4852 + }
4853 + }
4854 +
4855 + /**
4856 + *
4857 + * CPanel: Action refresh available backups.
4858 + *
4859 + * Save backups to DB for the selected cPanel server.
4860 + *
4861 + * @return void
4862 + */
4863 + public function cpanel_action_refresh_available_backups() {
4864 +
4865 + // Authenticate cPanel account.
4866 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4867 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4868 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4869 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4870 + $cpanel_site_path = $cpanel_authentication_credentials[0]['cpanel_site_path'];
4871 + $website_id = $cpanel_authentication_credentials[0]['website_id'];
4872 +
4873 + // Grab automatic WHM backups.
4874 + $api_response = static::call_cpanel_api( 'GET', '/execute/Restore/query_file_info?path=' . $cpanel_site_path . '&exists=1', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4875 + $all_backups = $api_response['response'];
4876 +
4877 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_available_backups', $all_backups );
4878 + Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'cpanel_auto' );
4879 +
4880 + // Grab manual account backups.
4881 + $manual_backups = static::get_cpanel_manual_account_backups();
4882 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_manual_backups', $manual_backups );
4883 +
4884 + Api_Backups_Utility::save_lasttime_backup( $website_id, $manual_backups, 'cpanel_manual' );
4885 +
4886 + // Grab manual DB backups.
4887 + $database_backups = static::get_cpanel_manual_database_backups( $website_id );
4888 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_manual_database_backups', $database_backups );
4889 +
4890 + // Grab WP-Toolkit backups.
4891 + $wp_toolkit_enabled = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_wp_toolkit' ) );
4892 + $wp_toolkit_enabled = isset( $wp_toolkit_enabled['mainwp_enable_wp_toolkit'] ) ? strtolower( $wp_toolkit_enabled['mainwp_enable_wp_toolkit'] ) : 0;
4893 + if ( $wp_toolkit_enabled ) {
4894 + $wp_toolkit_backups = static::get_cpanel_wp_toolkit_backups( $website_id );
4895 + if ( $wp_toolkit_backups ) {
4896 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_wp_toolkit_backups', $wp_toolkit_backups );
4897 + Api_Backups_Utility::save_lasttime_backup( $website_id, $wp_toolkit_backups, 'cpanel_wp_toolkit' );
4898 + }
4899 + }
4900 +
4901 + // Return AJAX.
4902 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4903 + // Store Last Backup timestamp.
4904 + if ( 'true' === $api_response['status'] ) {
4905 + wp_send_json( 'true' );
4906 + } else {
4907 + wp_die( 'false' );
4908 + }
4909 + }
4910 + }
4911 +
4912 + /**
4913 + *
4914 + * CPanel: Action restore selected backup.
4915 + *
4916 + * @return void
4917 + */
4918 + public function cpanel_action_restore_backup() {
4919 +
4920 + Api_Backups_Helper::security_nonce( 'cpanel_action_restore_backup' );
4921 +
4922 + // Authenticate cPanel account.
4923 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4924 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4925 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4926 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4927 + $cpanel_site_path = $cpanel_authentication_credentials[0]['cpanel_site_path'];
4928 +
4929 + // Grab website_id & backup_api name from Ajax post.
4930 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4931 + // Grab $_POST data.
4932 + $backup_id = isset( $_POST['backup_id'] ) ? wp_unslash( $_POST['backup_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4933 + }
4934 +
4935 + // Send Payload & create backup.
4936 + $api_response = static::call_cpanel_api( 'GET', '/execute/Restore/restore_file?backupID=' . $backup_id . '&path=' . $cpanel_site_path . '&overwrite=1', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4937 +
4938 + // Return AJAX.
4939 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4940 + // Store Last Backup timestamp.
4941 + if ( '200' === (string) $api_response['httpCode'] ) {
4942 + wp_send_json( 'true' );
4943 + } else {
4944 + wp_die( 'false' );
4945 + }
4946 + }
4947 + }
4948 +
4949 + /**
4950 + *
4951 + * CPanel: Action restore selected database backup.
4952 + *
4953 + * @return void
4954 + */
4955 + public function cpanel_action_restore_database_backup() {
4956 +
4957 + // Authenticate cPanel account.
4958 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4959 +
4960 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4961 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4962 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4963 +
4964 + // Grab website_id & backup_api name from Ajax post.
4965 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4966 + // Grab $_POST data.
4967 + $backup_id = isset( $_POST['backup_id'] ) ? wp_unslash( $_POST['backup_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4968 + $backup_path = isset( $_POST['backup_path'] ) ? wp_unslash( $_POST['backup_path'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4969 + }
4970 +
4971 + $backup_full_path = $backup_path . '/' . $backup_id;
4972 +
4973 + // Send Payload & create backup. https://{host}:{port}/execute/Backup/restore_databases?backup=database_file_name.sql.gz.
4974 + $api_response = static::call_cpanel_api( 'POST', '/execute/Backup/restore_databases?backup=' . $backup_full_path, $cpanel_baseurl, $cpanel_username, $cpanel_password );
4975 + // Return AJAX.
4976 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4977 + // Store Last Backup timestamp.
4978 + if ( '200' === (string) $api_response['httpCode'] ) {
4979 + wp_send_json( 'true' );
4980 + } else {
4981 + wp_die( 'false' );
4982 + }
4983 + }
4984 + }
4985 +
4986 + /**
4987 + *
4988 + * CPanel: Action restore selected manual backup.
4989 + *
4990 + * @return void
4991 + */
4992 + public function cpanel_action_restore_manual_backup() {
4993 +
4994 + // Authenticate cPanel account.
4995 + $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4996 +
4997 + $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4998 + $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4999 + $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
5000 +
5001 + // Grab website_id & backup_api name from Ajax post.
5002 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5003 + // Grab $_POST data.
5004 + $backup_id = isset( $_POST['backup_id'] ) ? wp_unslash( $_POST['backup_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
5005 + $backup_path = isset( $_POST['backup_path'] ) ? wp_unslash( $_POST['backup_path'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
5006 + }
5007 +
5008 + /**
5009 + * Output example for api call.:
5010 + * Endpoint: /execute/Backup/restore_files
5011 + * Backup file: backup-1.4.2024_17-45-59_cpanel-user.tar.gz
5012 + * Backup directory: /home/{cpanel-user}
5013 + * Backup full path: /home/{cpanel-user}/backup-1.4.2024_17-45-59_cpanel-user.tar.gz
5014 + *
5015 + * Https://{host}:{port}/execute/Backup/restore_files?backup=/home/{cpanel-user}/backup-1.4.2024_17-45-59_cpanel-user.tar.gz&directory=/home/{cpanel-user}.
5016 + */
5017 + $backup_full_path = $backup_path . '/' . $backup_id;
5018 + $directory = $backup_path;
5019 +
5020 + // Send Payload & create backup.
5021 + $api_response = static::call_cpanel_api( 'POST', '/execute/Backup/restore_files?backup=' . $backup_full_path . '&directory=' . $directory, $cpanel_baseurl, $cpanel_username, $cpanel_password );
5022 + $response_decoded = json_decode( $api_response['response'] );
5023 + $errors = $response_decoded->errors['0'];
5024 +
5025 + // Return AJAX.
5026 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5027 + // Store Last Backup timestamp.
5028 + if ( '200' === (string) $api_response['httpCode'] && empty( $errors ) ) {
5029 + wp_send_json( 'true' );
5030 + } else {
5031 + wp_die( 'false' );
5032 + }
5033 + }
5034 + }
5035 +
5036 + /*********************************************************************************
5037 + * Kinsta API Methods.
5038 + **********************************************************************************/
5039 +
5040 + /**
5041 + * Kinsta: action refresh available backups.
5042 + *
5043 + * Refresh available backups for the selected server.
5044 + *
5045 + * @return void
5046 + */
5047 + public function ajax_kinsta_action_refresh_available_backups() {
5048 + Api_Backups_Helper::security_nonce( 'kinsta_action_refresh_available_backups' );
5049 + static::kinsta_action_refresh_available_backups();
5050 + die();
5051 + }
5052 +
5053 + /**
5054 + * Kinsta: action create backup.
5055 + *
5056 + * Create backup for the selected server.
5057 + *
5058 + * @return void
5059 + */
5060 + public function ajax_kinsta_action_create_backup() {
5061 + Api_Backups_Helper::security_nonce( 'kinsta_action_create_backup' );
5062 + static::kinsta_action_create_backup();
5063 + die();
5064 + }
5065 +
5066 + /**
5067 + * Kinsta: action delete backup.
5068 + *
5069 + * Create backup for the selected server.
5070 + *
5071 + * @return void
5072 + */
5073 + public function ajax_kinsta_action_delete_backup() {
5074 + Api_Backups_Helper::security_nonce( 'kinsta_action_delete_backup' );
5075 + static::kinsta_action_delete_backup();
5076 + die();
5077 + }
5078 +
5079 + /**
5080 + * Kinsta: action restore backup.
5081 + *
5082 + * Restore backup for the selected server.
5083 + *
5084 + * @return void
5085 + */
5086 + public function ajax_kinsta_action_restore_backup() {
5087 + Api_Backups_Helper::security_nonce( 'kinsta_action_restore_backup' );
5088 + static::kinsta_action_restore_backup(); // ajax call.
5089 + die();
5090 + }
5091 +
5092 + /**
5093 + *
5094 + * Kinsta: Authentication.
5095 + *
5096 + * Grab needed authentication credentials for Kinsta API - either from global settings or individual settings.
5097 + *
5098 + * @param int $website_id Website ID.
5099 + *
5100 + * @return array
5101 + */
5102 + public static function get_kinsta_authentication_credentials( $website_id = null ) { //phpcs:ignore -- NOSONAR - complex.
5103 +
5104 + $kinsta_authentication_credentials = array();
5105 +
5106 + // Grab website_id & from Ajax post if $website_id is not set.
5107 + if ( empty( $website_id ) ) {
5108 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5109 + // Grab : $_POST['data'] submit values.
5110 + $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore -- nonce verified.
5111 + } else {
5112 + // Grab : $_GET['data'] from url if not Ajax call.
5113 + $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore -- nonce verified.
5114 + }
5115 + }
5116 +
5117 + // Global / Individual check.
5118 + $global_individual_check = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_kinsta_individual' ) );
5119 + $mainwp_enable_kinsta_individual = isset( $global_individual_check['mainwp_enable_kinsta_individual'] ) ? $global_individual_check['mainwp_enable_kinsta_individual'] : '0';
5120 +
5121 + if ( 'on' === $mainwp_enable_kinsta_individual ) {
5122 + // Grab cPanel baseurl, username & password.
5123 + $kinsta_baseurl = 'https://api.kinsta.com/v2';
5124 +
5125 + // Grab Kinsta password.
5126 + $kinsta_api_key = Api_Backups_Utility::get_instance()->get_child_api_key( $website_id, 'kinsta' );
5127 +
5128 + // Grab Kinsta Account Email.
5129 + $account_email = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_kinsta_account_email' ) );
5130 + $kinsta_account_email = isset( $account_email['mainwp_kinsta_account_email'] ) ? $account_email['mainwp_kinsta_account_email'] : null;
5131 +
5132 + // Grab Kinsta Company ID.
5133 + $company_id = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_kinsta_company_id' ) );
5134 + $kinsta_company_id = isset( $company_id['mainwp_kinsta_company_id'] ) ? $company_id['mainwp_kinsta_company_id'] : null;
5135 +
5136 + // Grab Kinsta Environment ID.
5137 + $environment_id = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_kinsta_environment_id' ) );
5138 + $kinsta_environment_id = isset( $environment_id['mainwp_kinsta_environment_id'] ) ? $environment_id['mainwp_kinsta_environment_id'] : null;
5139 +
5140 + } elseif ( '0' === $mainwp_enable_kinsta_individual ) {
5141 + // Grab Kinsta baseurl, username & password.
5142 + $kinsta_baseurl = 'https://api.kinsta.com/v2';
5143 +
5144 + // Grab Kinsta password.
5145 + $kinsta_api_key = static::get_kinsta_api_key();
5146 +
5147 + // Grab Kinsta Account Email.
5148 + $kinsta_account_email = get_option( 'mainwp_kinsta_api_account_email' );
5149 +
5150 + // Grab Kinsta Company ID.
5151 + $kinsta_company_id = get_option( 'mainwp_kinsta_company_id' );
5152 +
5153 + // Grab Kinsta Environment ID.
5154 + $environment_id = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_kinsta_environment_id' ) );
5155 + $kinsta_environment_id = isset( $environment_id['mainwp_kinsta_environment_id'] ) ? $environment_id['mainwp_kinsta_environment_id'] : null;
5156 + }
5157 +
5158 + // Build array.
5159 + $kinsta_authentication_credentials[] = array(
5160 + 'kinsta_baseurl' => $kinsta_baseurl,
5161 + 'kinsta_api_key' => $kinsta_api_key,
5162 + 'kinsta_environment_id' => $kinsta_environment_id,
5163 + 'website_id' => $website_id,
5164 + 'kinsta_company_id' => $kinsta_company_id,
5165 + 'kinsta_company_email' => $kinsta_account_email,
5166 + );
5167 +
5168 + return $kinsta_authentication_credentials;
5169 + }
5170 +
5171 + /**
5172 + * Call Kinsta API, Authenticate & perform given method.
5173 + *
5174 + * @param string $method GET|POST|PUT|DELETE.
5175 + * @param string $url API endpoint for the call.
5176 + * @param string $baseurl baseurl.
5177 + * @param string $api_key Kinsta API Key.
5178 + * @param string $action action.
5179 + * @param string $backup_data action.
5180 + *
5181 + * @return array Output from cPanel API.
5182 + */
5183 + public static function call_kinsta_api( $method, $url, $baseurl, $api_key, $action = '', $backup_data = array() ) {
5184 +
5185 + $curl = curl_init();
5186 +
5187 + $api_Key = $api_key;
5188 + curl_setopt_array(
5189 + $curl,
5190 + array(
5191 + CURLOPT_URL => $baseurl . $url,
5192 + CURLOPT_RETURNTRANSFER => true,
5193 + CURLOPT_ENCODING => '',
5194 + CURLOPT_MAXREDIRS => 10,
5195 + CURLOPT_TIMEOUT => 0,
5196 + CURLOPT_FOLLOWLOCATION => true,
5197 + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
5198 + CURLOPT_CUSTOMREQUEST => $method,
5199 + CURLOPT_POSTFIELDS => $backup_data,
5200 + CURLOPT_HTTPHEADER => array(
5201 + 'Content-Type: application/json',
5202 + "Authorization: Bearer $api_Key",
5203 + ),
5204 + )
5205 + );
5206 +
5207 + $resp = curl_exec( $curl );
5208 + $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
5209 +
5210 + $response['httpCode'] = $httpCode;
5211 + $response['response'] = $resp;
5212 +
5213 + if ( '202' !== $httpCode && '200' !== $httpCode ) {
5214 + $response['status'] = 'false';
5215 + } else {
5216 + $response['status'] = 'true';
5217 + }
5218 +
5219 + // Log API call.
5220 + $payload = "[Status] $httpCode :: [Action] $action :: [EndPoint] $baseurl$url";
5221 + $payload_response = "[Status] $httpCode :: [Action] $action :: [Response] $resp";
5222 + Api_Backups_Utility::log_debug( $payload );
5223 + Api_Backups_Utility::log_debug( $payload_response );
5224 +
5225 + curl_close( $curl );
5226 + return $response;
5227 + }
5228 +
5229 + /**
5230 + *
5231 + * Kinsta: Action get User ID.
5232 + *
5233 + * Get the User Id from the given Company ID & Email address.
5234 + *
5235 + * @return array
5236 + */
5237 + public static function kinsta_action_get_user_id() {
5238 +
5239 + // Authenticate kinsta account.
5240 + $kinsta_authentication_credentials = static::get_kinsta_authentication_credentials();
5241 + $kinsta_baseurl = $kinsta_authentication_credentials[0]['kinsta_baseurl'];
5242 + $kinsta_api_key = $kinsta_authentication_credentials[0]['kinsta_api_key'];
5243 + $kinsta_company_id = $kinsta_authentication_credentials[0]['kinsta_company_id'];
5244 + $kinsta_company_email = $kinsta_authentication_credentials[0]['kinsta_company_email'];
5245 +
5246 + $payload_url = '/company/' . $kinsta_company_id . '/users';
5247 +
5248 + // Send Payload.
5249 + $api_response = static::call_kinsta_api( 'GET', $payload_url, $kinsta_baseurl, $kinsta_api_key, '' );
5250 +
5251 + // Decode Response.
5252 + $response = json_decode( $api_response['response'] );
5253 + $company = $response->company;
5254 + $company_users = $company->users;
5255 +
5256 + // Grab correct user ID.
5257 + foreach ( $company_users as $user ) {
5258 + if ( $kinsta_company_email === $user->user->email ) {
5259 + $user_id = $user->user->id;
5260 + }
5261 + }
5262 +
5263 + // Return user id.
5264 + return $user_id;
5265 + }
5266 +
5267 + /**
5268 + *
5269 + * Kinsta: Action refresh available backups.
5270 + *
5271 + * Save backups to DB for the selected server.
5272 + *
5273 + * @param array $credentials Kinsta credentials.
5274 + * @param bool $return_result Return or not.
5275 + *
5276 + * @return mixed
5277 + */
5278 + public static function kinsta_action_refresh_available_backups( $credentials = array(), $return_result = false ) {
5279 +
5280 + // Authenticate kinsta account.
5281 + $kinsta_authentication_credentials = empty( $credentials ) || ! is_array( $credentials ) ? static::get_kinsta_authentication_credentials() : $credentials;
5282 + $kinsta_baseurl = $kinsta_authentication_credentials[0]['kinsta_baseurl'];
5283 + $kinsta_api_key = $kinsta_authentication_credentials[0]['kinsta_api_key'];
5284 + $kinsta_env_id = $kinsta_authentication_credentials[0]['kinsta_environment_id'];
5285 + $website_id = $kinsta_authentication_credentials[0]['website_id'];
5286 + $downloadable_backups = '';
5287 +
5288 + $action = 'kinsta_action_refresh_available_backups';
5289 +
5290 + // Grab backup meta.
5291 + $api_response = static::call_kinsta_api( 'GET', '/sites/environments/' . $kinsta_env_id . '/backups', $kinsta_baseurl, $kinsta_api_key, $action );
5292 +
5293 + $success = false;
5294 +
5295 + if ( 'true' === $api_response['status'] ) {
5296 + $all_backups = $api_response['response'];
5297 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_kinsta_available_backups', $all_backups );
5298 + Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'kinsta' );
5299 +
5300 + $action = 'kinsta_action_refresh_available_backups_downloadable';
5301 +
5302 + $downloadable_backups = static::call_kinsta_api( 'GET', '/sites/environments/' . $kinsta_env_id . '/downloadable-backups', $kinsta_baseurl, $kinsta_api_key, $action );
5303 + $success = true;
5304 + } else {
5305 + Api_Backups_Utility::log_debug( 'Kinsta API Error: ' . $api_response['response'] );
5306 + }
5307 + if ( $downloadable_backups ) {
5308 + if ( 'true' === $downloadable_backups['status'] ) {
5309 + $downloadable_backups = $downloadable_backups['response'];
5310 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_kinsta_downloadable_backups', $downloadable_backups );
5311 + }
5312 + } else {
5313 + Api_Backups_Utility::log_debug( 'Kinsta API Error: There was an issue while refreshing available backups.' );
5314 + }
5315 +
5316 + if ( $return_result ) {
5317 + return $success;
5318 + }
5319 +
5320 + // Return AJAX.
5321 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5322 + // Store Last Backup timestamp.
5323 + if ( 'true' === $api_response['status'] ) {
5324 + wp_send_json( 'true' );
5325 + } else {
5326 + wp_die( 'false' );
5327 + }
5328 + }
5329 + }
5330 +
5331 + /**
5332 + *
5333 + * Kinsta: Action create manual backup.
5334 + *
5335 + * Create a Plesk Backup.
5336 + *
5337 + * @param bool $resturn_values resturn values.
5338 + * @param int $site_id website id.
5339 + *
5340 + * @return mixed result.
5341 + */
5342 + public static function kinsta_action_create_backup( $resturn_values = false, $site_id = null ) {
5343 +
5344 + // Authenticate kinsta account.
5345 + $kinsta_authentication_credentials = static::get_kinsta_authentication_credentials( $site_id );
5346 + $kinsta_baseurl = $kinsta_authentication_credentials[0]['kinsta_baseurl'];
5347 + $kinsta_api_key = $kinsta_authentication_credentials[0]['kinsta_api_key'];
5348 + $kinsta_env_id = $kinsta_authentication_credentials[0]['kinsta_environment_id'];
5349 + $website_id = $kinsta_authentication_credentials[0]['website_id'];
5350 +
5351 + // Grab Child Site options.
5352 + $website = Api_Backups_Helper::get_website_by_id( $website_id );
5353 +
5354 + // Prepare Backup Payload.
5355 + $backup_data = array(
5356 + 'tag' => 'MainWP API Backups - ' . $website['name'],
5357 + );
5358 + $backup_data = wp_json_encode( $backup_data );
5359 +
5360 + // Send Payload & create backup.
5361 + $api_response = static::call_kinsta_api( 'POST', '/sites/environments/' . $kinsta_env_id . '/manual-backups', $kinsta_baseurl, $kinsta_api_key, $backup_data );
5362 +
5363 + if ( is_array( $api_response ) && isset( $api_response['status'] ) && 'true' === $api_response['status'] ) {
5364 + // Save Timestamp.
5365 + $local_time = current_datetime();
5366 + $current_time = $local_time->getTimestamp() + $local_time->getOffset();
5367 + Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_kinsta_last_backup', $current_time );
5368 + }
5369 +
5370 + if ( $resturn_values ) {
5371 + return $api_response;
5372 + }
5373 +
5374 + // Return AJAX.
5375 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5376 + // Store Last Backup timestamp.
5377 + if ( 'true' === $api_response['status'] ) {
5378 + wp_send_json( 'true' );
5379 + } else {
5380 + wp_die( 'false' );
5381 + }
5382 + }
5383 + }
5384 +
5385 + /**
5386 + *
5387 + * Kinsta: Action create manual backup.
5388 + *
5389 + * Create a Plesk Backup.
5390 + *
5391 + * @param bool $return_values return values.
5392 + *
5393 + * @return array
5394 + */
5395 + public static function kinsta_action_delete_backup( $return_values = false ) {
5396 +
5397 + $backup_id = isset( $_POST['backup_id'] ) ? wp_unslash( $_POST['backup_id'] ) : ''; //phpcs:ignore -- nonce verified.
5398 +
5399 + // Authenticate kinsta account.
5400 + $kinsta_authentication_credentials = static::get_kinsta_authentication_credentials();
5401 + $kinsta_baseurl = $kinsta_authentication_credentials[0]['kinsta_baseurl'];
5402 + $kinsta_api_key = $kinsta_authentication_credentials[0]['kinsta_api_key'];
5403 +
5404 + $payload_url = '/sites/environments/backups/' . $backup_id;
5405 +
5406 + // Send Payload & create backup.
5407 + $api_response = static::call_kinsta_api( 'DELETE', $payload_url, $kinsta_baseurl, $kinsta_api_key, '' );
5408 +
5409 + if ( is_array( $api_response ) && isset( $api_response['status'] ) && 'true' === $api_response['status'] ) {
5410 + static::kinsta_action_refresh_available_backups( $kinsta_authentication_credentials, true );
5411 + }
5412 +
5413 + if ( $return_values ) {
5414 + return $api_response;
5415 + }
5416 +
5417 + // Return AJAX.
5418 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5419 + // Store Last Backup timestamp.
5420 + if ( 'true' === $api_response['status'] ) {
5421 + wp_send_json( 'true' );
5422 + } else {
5423 + wp_die( 'false' );
5424 + }
5425 + }
5426 + }
5427 +
5428 + /**
5429 + *
5430 + * Kinsta: Action restore manual backup.
5431 + *
5432 + * Restore a selected Backup.
5433 + *
5434 + * @param bool $return_values return or not.
5435 + *
5436 + * @return array
5437 + */
5438 + public static function kinsta_action_restore_backup( $return_values = false ) {
5439 +
5440 + $backup_id = isset( $_POST['backup_id'] ) ? intval( $_POST['backup_id'] ) : 0; //phpcs:ignore -- nonce verified.
5441 +
5442 + // Authenticate kinsta account.
5443 + $kinsta_authentication_credentials = static::get_kinsta_authentication_credentials();
5444 + $kinsta_baseurl = $kinsta_authentication_credentials[0]['kinsta_baseurl'];
5445 + $kinsta_api_key = $kinsta_authentication_credentials[0]['kinsta_api_key'];
5446 + $kinsta_env_id = $kinsta_authentication_credentials[0]['kinsta_environment_id'];
5447 +
5448 + $company_user_id = static::kinsta_action_get_user_id();
5449 +
5450 + $payload_url = '/sites/environments/' . $kinsta_env_id . '/backups/restore';
5451 +
5452 + // Prepare Backup Payload.
5453 + $backup_data = array(
5454 + 'backup_id' => $backup_id,
5455 + 'notified_user_id' => $company_user_id,
5456 + );
5457 + $backup_data = wp_json_encode( $backup_data );
5458 +
5459 + // Send Payload & create backup.
5460 + $api_response = static::call_kinsta_api( 'POST', $payload_url, $kinsta_baseurl, $kinsta_api_key, '', $backup_data );
5461 +
5462 + if ( $return_values ) {
5463 + return $api_response;
5464 + }
5465 +
5466 + // Return AJAX.
5467 + if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5468 + // Store Last Backup timestamp.
5469 + if ( 'true' === $api_response['status'] ) {
5470 + wp_send_json( 'true' );
5471 + } else {
5472 + wp_die( 'false' );
5473 + }
5474 + }
5475 + }
5476 +
5477 + // END class MainWP_3rdParty_Backup.
4539 5478 }