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