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