PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.23
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.23
5.5.84 5.5.83 5.5.82 5.5.81 5.5.80 5.5.79 5.5.77 5.5.76 5.5.75 5.5.73 5.5.72 5.5.22 5.5.23 5.5.29 5.5.3 5.5.31 5.5.32 5.5.34 5.5.35 5.5.36 5.5.37 5.5.4 5.5.40 5.5.41 5.5.42 All 160 releases
wp-data-access / WPDataAccess / Backup / WPDA_Data_Export.php

WPDA_Data_Export.php in WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards 5.5.23, at WPDataAccess/Backup/WPDA_Data_Export.php

1,162 lines 44.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignore Standard.Category.SniffName.ErrorCode
2 /**
3 * Suppress "error - 0 - No summary was found for this file" on phpdoc generation
4 *
5 * @package WPDataAccess\Backup
6 */
7
8 namespace WPDataAccess\Backup {
9
10 use Dropbox\Dropbox;
11 use Dropbox\Dropbox\Auth;
12 use WPDataAccess\Data_Dictionary\WPDA_Dictionary_Lists;
13 use WPDataAccess\Settings\WPDA_Settings_DataBackup;
14 use WPDataAccess\Utilities\WPDA_Export_Sql;
15 use WPDataAccess\Utilities\WPDA_Remote_Call;
16 use WPDataAccess\WPDA;
17 use WPDataAccess\Utilities\WPDA_Message_Box;
18 use WPDataAccess\Utilities\WPDA_Repository;
19
20 /**
21 * Class WPDA_Data_Export
22 *
23 * This class offers support to manage unattended data exports. Data exports can be run once only or scheduled.
24 * Every data backup has a unique name to identify it. The data backup name is used in combination with the date
25 * and time to create a unique file name.
26 *
27 * @author Peter Schulz
28 * @since 1.0.0
29 */
30 class WPDA_Data_Export {
31
32 const PREFIX_RUNONCE = 'wpda-run-once-';
33 const SHOW_JOBS_OPTION_NAME = 'wpda_data_backup_show_jobs';
34
35 /**
36 * Holds the scheduled cron jobs
37 *
38 * @var array
39 */
40 protected $schedules;
41
42 /**
43 * WPDA_Data_Export constructor
44 *
45 * Gets and stores the scheduled cron jobs.
46 */
47 public function __construct() {
48 $this->schedules = wp_get_schedules();
49 }
50
51 /**
52 * Data entry form to add or update a data backup
53 *
54 * @param string $action Add for new export; Update to edit existing export.
55 */
56 public function create_export( $action ) {
57 $wpda_db_options_activated = get_option( 'wpda_db_options_activated' );
58 if ( ! is_array( $wpda_db_options_activated ) || 0 === count( $wpda_db_options_activated ) ) {//phpcs:ignore - 8.1 proof
59 echo '<br/>';
60 echo __( 'You need to define and activate at least one storage device in Data Backup Settings to use this feature.', 'wp-data-access' ); // phpcs:ignore WordPress.Security.EscapeOutput
61 echo '<br/>';
62 echo '<a href="?page=wpdataaccess&tab=databackup">&raquo; ';
63 echo __( 'Define and/or activate a storage device', 'wp-data-access' ); // phpcs:ignore WordPress.Security.EscapeOutput
64 echo '</a>';
65 wp_die();
66 }
67
68 if ( isset( $_REQUEST['wpdaschema_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
69 $schema_name = sanitize_text_field( wp_unslash( $_REQUEST['wpdaschema_name'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
70 } else {
71 $schema_name = '';
72 }
73
74 $device_arg = '';
75 if ( 'update' === $action ) {
76 if ( isset( $_REQUEST['schedule'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
77 $schedule = sanitize_text_field( wp_unslash( $_REQUEST['schedule'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
78 if ( 'wpda_data_backup' !== $schedule ) {
79 wp_die( __( 'ERROR: Wrong arguments', 'wp-data-access' ) ); // phpcs:ignore WordPress.Security.EscapeOutput
80 }
81 } else {
82 wp_die( __( 'ERROR: Wrong arguments', 'wp-data-access' ) ); // phpcs:ignore WordPress.Security.EscapeOutput
83 }
84 if ( isset( $_REQUEST['schedule_args'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
85 $backupid = sanitize_text_field( wp_unslash( $_REQUEST['schedule_args'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
86 } else {
87 wp_die( __( 'ERROR: Wrong arguments', 'wp-data-access' ) ); // phpcs:ignore WordPress.Security.EscapeOutput
88 }
89 $data_backups = get_option( 'wpda_data_backup_option' );
90 $data_backup_found = false;
91 foreach ( $data_backups as $data_backup ) {
92 if ( $data_backup['id'] === $backupid ) {
93 $data_backup_tables = $data_backup['tables'];
94 $keep = $data_backup['keep'];
95 $schema_name = isset( $data_backup['schema_name'] ) ? $data_backup['schema_name'] : '';
96 $data_backup_found = true;
97 }
98 }
99 if ( ! $data_backup_found ) {
100 wp_die( __( 'ERROR: Wrong arguments', 'wp-data-access' ) ); // phpcs:ignore WordPress.Security.EscapeOutput
101 }
102 if ( isset( $_REQUEST['interval'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
103 $interval = sanitize_text_field( wp_unslash( $_REQUEST['interval'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
104 }
105 if ( isset( $_REQUEST['device'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
106 $device_arg = sanitize_text_field( wp_unslash( $_REQUEST['device'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
107 }
108 } else {
109 $backupid = '';
110 }
111
112 $table_list = WPDA_Dictionary_Lists::get_tables( false, $schema_name );
113 ?>
114 <div class="wrap">
115 <h1 class="wp-heading-inline">
116 <?php echo __( 'Data Backup' ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
117 </h1>
118 <div id="wpda_export_import">
119 <div class="wpda_export_import">
120 <form id="wpda_export_import_form"
121 action="?page=wpda&page_action=wpda_backup"
122 method="post"
123 onsubmit="return pre_submit()">
124 <table>
125 <tr>
126 <td style="font-weight:bold;padding-left:10px;"><?php echo __( 'Database Tables' ); // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
127 <td></td>
128 <td style="font-weight:bold;padding-left:10px"><?php echo __( 'Tables To Be Exported' ); // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
129 </tr>
130 <tr>
131 <td>
132 <select id="wpda_table_name_db" name="wpda_table_name_db" multiple size="20"
133 style="width:300px;">
134 <?php
135 foreach ( $table_list as $key => $value ) {
136 echo '<option value="' . esc_attr( $value['table_name'] ) . '">' . esc_attr( $value['table_name'] ) . '</option>';
137 }
138 ?>
139 </select>
140 </td>
141 <td>
142 <a href="javascript:void(0)" class="button" onclick="move_all_to_export()">
143 >>> </a>
144 <br/>
145 <a href="javascript:void(0)" class="button" onclick="move_all_to_db()"> <<< </a>
146 </td>
147 <td>
148 <select id="wpda_table_name_export" name="wpda_table_name_export[]" multiple
149 size="20" style="width:300px;">
150 </select>
151 </td>
152 </tr>
153 <tr>
154 <td colspan="3" style="text-align:center;">
155 <table align="center">
156 <tr>
157 <td style="text-align:right;"><?php echo __( 'Backup Id' ); // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
158 <td style="text-align:left;">
159 <input
160 type="text"
161 id="backupid"
162 name="backupid"
163 value="<?php echo esc_attr( $backupid ); ?>"
164 maxlength="50"
165 <?php
166 if ( 'update' === $action ) {
167 echo 'readonly';
168 }
169 ?>
170 />
171 </td>
172 </tr>
173 <tr>
174 <td style="text-align:right;"><?php echo __( 'Backup Interval' ); // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
175 <td style="text-align:left;">
176 <select id="interval" name="interval">
177 <?php if ( 'add' === $action ) { ?>
178 <option value="runonce"><?php echo __( 'Run once (no interval)' ); // phpcs:ignore WordPress.Security.EscapeOutput ?></option>
179 <?php } ?>
180 <?php
181 foreach ( $this->schedules as $key => $schedule ) {
182 echo '<option value="' . esc_attr( $key ) . '">' .
183 esc_attr( $schedule['display'] ) . ' (' . esc_attr( $schedule['interval'] ) . ' sec)' .
184 '</option>';
185 }
186 ?>
187 </select>
188 </td>
189 </tr>
190 <tr>
191 <td style="text-align:right;"><?php echo __( 'Backup Location' ); // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
192 <td style="text-align:left;">
193 <select id="device" name="device">
194 <?php
195 foreach ( $wpda_db_options_activated as $key => $value ) {
196 $device = $key;
197 if ( 'local_path' === $key ) {
198 $device = 'local > ' . WPDA::get_option( WPDA::OPTION_DB_LOCAL_PATH );
199 } elseif ( 'dropbox' === $key ) {
200 $dropbox_path = WPDA::get_option( WPDA::OPTION_DB_DROPBOX_PATH );
201 if ( '' === $dropbox_path ) {
202 $dropbox_path = '/wp-data-access-backups/'; // Use last version.
203 }
204 $device = 'dropbox > ' . $dropbox_path;
205 }
206 echo '<option value="' . esc_attr( $key ) . '"' . ( $key === $device_arg ? 'selected' : '' ) . '>' .
207 esc_attr( $device ) .
208 '</option>';
209 }
210 ?>
211 </select>
212 </td>
213 </tr>
214 <tr>
215 <td style="text-align:right;"><?php echo __( 'Backup Files Kept' ); // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
216 <td style="text-align:left;">
217 <select id="keep" name="keep">
218 <option value="1">1</option>
219 <option value="2">2</option>
220 <option value="3">3</option>
221 <option value="4">4</option>
222 <option value="5">5</option>
223 <option value="6">6</option>
224 <option value="7">7</option>
225 <option value="8">8</option>
226 <option value="9">9</option>
227 <option value="10">10</option>
228 <option value="ALL">ALL</option>
229 </select>
230 </td>
231 </tr>
232 <tr>
233 <td></td>
234 <td style="text-align:left;">
235 <button type="submit" class="button button-primary">
236 <i class="fas fa-check wpda_icon_on_button"></i>
237 <?php echo __( 'Start' ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
238 </button>
239 <button type="button" class="button button-secondary"
240 onclick="window.location.href=window.location.href">
241 <i class="fas fa-times-circle wpda_icon_on_button"></i>
242 <?php echo __( 'Cancel' ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
243 </button>
244 </td>
245 </tr>
246 </table>
247 </td>
248 </tr>
249 </table>
250 <input type="hidden" name="wpdaschema_name" value="<?php echo esc_attr( $schema_name ); ?>"/>
251 <input type="hidden" name="action" value="<?php echo esc_attr( $action ); ?>"/>
252 <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( $this->get_wp_nonce() ); ?>"/>
253 </form>
254 </div>
255 </div>
256 </div>
257 <script type='text/javascript'>
258 var tables_selected = [];
259 <?php
260 if ( 'update' === $action ) {
261 foreach ( $data_backup_tables as $data_backup_table ) {
262 ?>
263 tables_selected.push('<?php echo esc_attr( $data_backup_table ); ?>');
264 <?php
265 }
266 ?>
267 jQuery(function () {
268 jQuery("#keep option[value='<?php echo esc_attr( $keep ); ?>']").prop('selected', true);
269 jQuery("#interval option[value='<?php echo esc_attr( $interval ); ?>']").prop('selected', true);
270 for (var i = 0; i < tables_selected.length; i++) {
271 jQuery("#wpda_table_name_db option[value='" + tables_selected[i] + "']").remove();
272 jQuery('#wpda_table_name_export').append(jQuery('<option>', {
273 value: tables_selected[i],
274 text: tables_selected[i]
275 }));
276 }
277 });
278 <?php
279 } else {
280 ?>
281 jQuery(function () {
282 jQuery("#keep option[value='3']").prop('selected', true);
283 jQuery( '.wpda_tooltip' ).tooltip();
284 });
285 <?php
286 }
287 ?>
288 function pre_submit() {
289 if (0 === jQuery("#wpda_table_name_export > option").length) {
290 alert('<?php echo __( 'No tables to be exported' ); // phpcs:ignore WordPress.Security.EscapeOutput ?>');
291 return false;
292 }
293 if ('' === jQuery("#backupid").val().trim()) {
294 alert('<?php echo __( 'You must specify a backupid' ); // phpcs:ignore WordPress.Security.EscapeOutput ?>');
295 return false;
296 }
297 jQuery("#wpda_table_name_export > option").each(function () {
298 jQuery(this).attr("selected", "true");
299 });
300 return true;
301 }
302
303 function move_all_to_export() {
304 jQuery("#wpda_table_name_db > option").each(function () {
305 jQuery('#wpda_table_name_export').append(jQuery('<option>', {
306 value: this.text,
307 text: this.text
308 }));
309 });
310 jQuery('#wpda_table_name_db > option').remove();
311 }
312
313 function move_all_to_db() {
314 jQuery("#wpda_table_name_export > option").each(function () {
315 jQuery('#wpda_table_name_db').append(jQuery('<option>', {
316 value: this.text,
317 text: this.text
318 }));
319 });
320 jQuery('#wpda_table_name_export > option').remove();
321 }
322
323 jQuery(function () {
324 jQuery('#wpda_table_name_db').on('click', function (event) {
325 if ('' !== event.target.text && undefined != event.target.text) {
326 jQuery('#wpda_table_name_export').append(jQuery('<option>', {
327 value: event.target.text,
328 text: event.target.text
329 }));
330 jQuery("#wpda_table_name_db option[value='" + event.target.text + "']").remove();
331 }
332 });
333 jQuery('#wpda_table_name_export').on('click', function (event) {
334 if ('' !== event.target.text && undefined != event.target.text) {
335 jQuery('#wpda_table_name_db').append(jQuery('<option>', {
336 value: event.target.text,
337 text: event.target.text
338 }));
339 jQuery("#wpda_table_name_export option[value='" + event.target.text + "']").remove();
340 }
341 });
342 });
343 </script>
344 <?php
345 }
346
347 /**
348 * Show available cron jobs
349 *
350 * Shows data backups only be default. Other cron jobs can be displayed as well.
351 */
352 public function show_wp_cron() {
353 $wpda_repository = new WPDA_Repository();
354 $wpda_repository->inform_user();
355
356 $no_data_backup_events = 0;
357 $data_backups = get_option( 'wpda_data_backup_option' );
358 $data_backups_keep = array();
359 $data_backups_device = array();
360 if ( null !== $data_backups && false !== $data_backups ) {
361 foreach ( $data_backups as $data_backup ) {
362 $data_backups_keep[ $data_backup['id'] ] = $data_backup['keep'];
363 $data_backups_device[ $data_backup['id'] ] = $data_backup['device'];
364 }
365 }
366
367 $crons = _get_cron_array();
368 $data_backups_found = false;
369 foreach ( $crons as $key => $cron ) {
370 foreach ( $cron as $key => $value ) {
371 if ( 'wpda_data_backup' === $key ) {
372 $data_backups_found = true;
373 continue;
374 }
375 }
376 if ( $data_backups_found ) {
377 continue;
378 }
379 }
380
381 if ( isset( $_REQUEST['show_jobs'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
382 $show_jobs = sanitize_text_field( wp_unslash( $_REQUEST['show_jobs'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
383 update_option( self::SHOW_JOBS_OPTION_NAME, $show_jobs );
384 } else {
385 $show_jobs = get_option( self::SHOW_JOBS_OPTION_NAME, 'wpda' );
386 }
387
388 if ( isset( $_REQUEST['wpdaschema_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
389 $schema_name = sanitize_text_field( wp_unslash( $_REQUEST['wpdaschema_name'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
390 } else {
391 $schema_name = '';
392 }
393
394 global $wpdb;
395
396 echo '<div class="wrap">';
397 echo '<h1 class="wp-heading-inline">';
398 echo __( 'Data Backup' ); // phpcs:ignore WordPress.Security.EscapeOutput
399 echo '</h1>';
400
401 if ( $data_backups_found || 'all' === $show_jobs ) {
402 echo '<table cellpadding="3" cellspacing="3" border="0" style="border-collapse:collapse;">';
403 echo '<tr>';
404 echo '<th></th>';
405 echo '<th></th>';
406 echo '<th style="text-align:left;">' . __( 'Hook Name' ) . '</th>'; // phpcs:ignore WordPress.Security.EscapeOutput
407 echo '<th style="text-align:left;">' . __( 'Arguments' ) . '</th>'; // phpcs:ignore WordPress.Security.EscapeOutput
408 echo '<th style="text-align:left;">' . __( 'Interval' ) . '</th>'; // phpcs:ignore WordPress.Security.EscapeOutput
409 echo '<th style="text-align:left;">' . __( 'Next Execution' ) . '</th>'; // phpcs:ignore WordPress.Security.EscapeOutput
410 echo '<th style="text-align:left;">' . __( 'Backup Location' ) . '</th>'; // phpcs:ignore WordPress.Security.EscapeOutput
411 echo '<th style="text-align:left;">' . __( 'Files Kept' ) . '</th>'; // phpcs:ignore WordPress.Security.EscapeOutput
412 echo '<th colspan="2" style="text-align:left;">' . __( 'Status' ) . '</th>'; // phpcs:ignore WordPress.Security.EscapeOutput
413 echo '</tr>';
414 foreach ( $crons as $key => $cron ) {
415 foreach ( $cron as $key => $value ) {
416 if ( 'wpda_data_backup' === $key ) {
417 // Filter run once jobs.
418 $is_runonce = false;
419 foreach ( $value as $value_key => $value_value ) {
420 if ( isset( $value_value['args'][0] ) && substr( $value_value['args'][0], 0, 14 ) === 'wpda-run-once-' ) {
421 $is_runonce = true;
422 continue;
423 }
424 }
425 if ( $is_runonce ) {
426 continue;
427 }
428 $style = 'style="background-color:#ffffff;"';
429 $no_data_backup_events ++;
430 } else {
431 $style = '';
432 if ( 'all' !== $show_jobs ) {
433 // Hide other cron jobs.
434 continue;
435 }
436 }
437 echo '<tr ' . esc_attr( $style ) . '>';
438 if ( 'wpda_data_backup' === $key ) {
439 echo '<td>';
440 echo '<form method="post" action="?page=wpda&page_action=wpda_backup">';
441 echo '<a href="javascript:void(0)" onclick="if (confirm(\'Are you sure you want to delete this data backup job?\')) { jQuery(this).closest(\'form\').submit(); }" class="dashicons dashicons-trash"></a>';
442 echo '<input type="hidden" name="action" value="remove" />';
443 echo '<input type="hidden" name="schedule" value="' . esc_attr( $key ) . '" />';
444 foreach ( $value as $value_key => $value_value ) {
445 $schedule_args = isset( $value_value['args'][0] ) ? $value_value['args'][0] : '';
446 echo '<input type="hidden" name="schedule_args" value="' . esc_attr( $schedule_args ) . '" />';
447 }
448 echo '<input type="hidden" name="wp_nonce" value="' . $this->get_wp_nonce() . '" />';
449 echo '</form>';
450 echo '</td>';
451 echo '<td>';
452 echo '<form method="post" action="?page=wpda&page_action=wpda_backup">';
453 echo '<a href="javascript:void(0)" onclick="jQuery(this).closest(\'form\').submit()" class="dashicons dashicons-edit"></a>';
454 echo '<input type="hidden" name="action" value="edit" />';
455 echo '<input type="hidden" name="schedule" value="' . esc_attr( $key ) . '" />';
456 foreach ( $this->schedules as $schedule_key => $schedule ) {
457 if ( $schedule['display'] === $this->schedules[ $value_value['schedule'] ]['display'] ) {
458 $interval = $schedule_key;
459 }
460 }
461 foreach ( $value as $value_key => $value_value ) {
462 echo '<input type="hidden" name="schedule_args" value="' . esc_attr( $value_value['args'][0] ) . '" />';
463 echo '<input type="hidden" name="interval" value="' . esc_attr( $interval ) . '" />';
464 }
465 if ( isset( $data_backups_keep[ $value_value['args'][0] ] ) ) {
466 echo '<input type="hidden" name="device" value="' . esc_attr( $data_backups_device[ $value_value['args'][0] ] ) . '" />';
467 }
468 echo '<input type="hidden" name="wp_nonce" value="' . $this->get_wp_nonce() . '" />';
469 echo '</form>';
470 echo '</td>';
471 } else {
472 echo '<td>';
473 echo '</td>';
474 echo '<td>';
475 echo '</td>';
476 }
477 echo '<td>';
478 echo esc_attr( $key );
479 echo '</td>';
480 foreach ( $value as $value_key => $value_value ) {
481 echo '<td>';
482 if ( is_array ($value_value['args']) &&
483 0 < count( $value_value['args'] ) ) {//phpcs:ignore - 8.1 proof
484 foreach ( $value_value['args'] as $arg ) {
485 if ( reset( $value_value['args'] ) !== $arg ) {//phpcs:ignore - 8.1 proof
486 echo ',';
487 }
488 echo esc_attr( $arg );
489 }
490 } else {
491 echo '-';
492 }
493 echo '</td>';
494 echo '<td>';
495 if ( isset( $this->schedules[ $value_value['schedule'] ]['display'] ) ) {
496 echo esc_attr( $this->schedules[ $value_value['schedule'] ]['display'] );
497 if ( isset( $value_value['interval'] ) ) {
498 echo ' (' . esc_attr( $value_value['interval'] ) . ' sec)';
499 }
500 }
501 echo '</td>';
502 echo '<td>';
503 $next = wp_next_scheduled( $key, $value_value['args'] );
504 echo esc_attr( get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $next ) ) );
505 echo '</td>';
506 echo '<td>';
507 if ( 'wpda_data_backup' === $key ) {
508 if ( isset( $data_backups_device[ $value_value['args'][0] ] ) ) {
509 echo esc_attr( $data_backups_device[ $value_value['args'][0] ] );
510 }
511 }
512 echo '</td>';
513 echo '<td>';
514 if ( 'wpda_data_backup' === $key ) {
515 if ( isset( $data_backups_keep[ $value_value['args'][0] ] ) ) {
516 echo esc_attr( $data_backups_keep[ $value_value['args'][0] ] );
517 }
518 }
519 echo '</td>';
520 echo '<td>';
521 if ( 'wpda_data_backup' === $key ) {
522 echo '<form method="post" action="?page=wpda">';
523 echo '<input type="hidden" name="table_name" value="' . esc_attr( $wpdb->prefix ) . 'wpda_logging" />';
524 echo '<input type="hidden" name="wpda_s" value="' . esc_attr( $value_value['args'][0] ) . '" />';
525 echo '<a href="javascript:void(0)" onclick="jQuery(this).closest(\'form\').submit()" class="dashicons dashicons-info"></a>';
526 echo '</form>';
527 }
528 echo '</td>';
529 echo '<td>';
530 if ( 'wpda_data_backup' === $key ) {
531 $resultset = $wpdb->get_results(
532 $wpdb->prepare(
533 "
534 SELECT `log_time`, `log_type`, `log_msg`
535 FROM `{$wpdb->prefix}wpda_logging`
536 WHERE `log_id` = %s
537 ORDER BY `log_time` desc limit 1",
538 array(
539 $value_value['args'][0],
540 )
541 ),
542 'ARRAY_A'
543 ); // db call ok; no-cache ok.
544 if ( 1 === $wpdb->num_rows ) {
545 echo esc_attr( $resultset[0]['log_type'] ) . ': ' .
546 esc_attr( $resultset[0]['log_msg'] ) .
547 ' (' . esc_attr( $resultset[0]['log_time'] ) . ')';
548 } else {
549 echo __( 'No logging information found' ); // phpcs:ignore WordPress.Security.EscapeOutput
550 }
551 }
552 echo '</td>';
553 }
554 echo '</tr>';
555 }
556 }
557 echo '</table>';
558 echo '<table style="margin-top:10px">';
559 echo '<tr>';
560 echo '<td><strong>' . esc_attr( $no_data_backup_events ) . ' data backup job' .
561 ( 1 < $no_data_backup_events ? 's' : '' ) . ' scheduled</strong></td>';
562 } else {
563 echo '<table>';
564 echo '<tr>';
565 echo '<td><strong>' . __( 'No data backup jobs found' ) . '</strong></td>'; // phpcs:ignore WordPress.Security.EscapeOutput
566 }
567 echo '<td>';
568 echo '<form method="post" action="?page=wpda&page_action=wpda_backup" style="display: inline-block; vertical-align: unset;">';
569 echo '<select name="show_jobs" onchange="jQuery(this).closest(\'form\').submit()" >';
570 echo '<option value="wpda"' . ( 'all' !== $show_jobs ? 'selected' : '' ) . '>' . __( 'Show plugin jobs only' ) . '</option>'; // phpcs:ignore WordPress.Security.EscapeOutput
571 echo '<option value="all"' . ( 'all' === $show_jobs ? 'selected' : '' ) . '>' . __( 'Show all WordPress jobs' ) . '</option>'; // phpcs:ignore WordPress.Security.EscapeOutput
572 echo '</select>';
573 echo '<input type="hidden" name="wp_nonce" value="' . $this->get_wp_nonce() . '" />';
574 echo '</form>';
575 echo '</td>';
576 echo '</tr>';
577 echo '</table>';
578 echo '</div>';
579 ?>
580 <script type="text/javascript">
581 jQuery(function () {
582 jQuery( '.wpda_tooltip' ).tooltip();
583 });
584 // Add toolbar events
585 jQuery("#wpda_toolbar_icon_add_backup").on("click", function() {
586 jQuery("#wpda_new_backup_wpdaschema_name").val("<?php echo esc_attr( $schema_name ); ?>");
587 jQuery("#wpda_new_backup").submit();
588 });
589 </script>
590 <?php
591 }
592
593 /**
594 * Prepares an unattended data backup (export)
595 *
596 * @param string $backupid Unique ID that identifies a data backup.
597 */
598 public function wpda_data_backup( $backupid ) {
599 $is_runonce_data_backup = substr( $backupid, 0, strlen( self::PREFIX_RUNONCE ) ) === self::PREFIX_RUNONCE;
600 if ( $is_runonce_data_backup ) {
601 // Run once data backup.
602 $data_backups = get_option( 'wpda_data_backup_option_runonce' );
603 // Directly remove data backup to prevent multiple backups.
604 $data_backups_new = array();
605 foreach ( $data_backups as $data_backup ) {
606 if ( $data_backup['id'] !== $backupid ) {
607 array_push( $data_backups_new, $data_backup );//phpcs:ignore - 8.1 proof
608 }
609 }
610 update_option( 'wpda_data_backup_option_runonce', $data_backups_new );
611 } else {
612 // Data backup job.
613 $data_backups = get_option( 'wpda_data_backup_option' );
614 }
615
616 foreach ( $data_backups as $data_backup ) {
617 if ( $data_backup['id'] === $backupid ) {
618 if ( $is_runonce_data_backup ) {
619 $user_backupid = substr( $backupid, strlen( self::PREFIX_RUNONCE ) );
620 } else {
621 $user_backupid = $backupid;
622 }
623
624 $keep = $data_backup['keep'];
625 $device = $data_backup['device'];
626 $schema = $data_backup['schema_name'];
627 $tables = $data_backup['tables'];
628
629 $this->wpda_data_backup_run( $user_backupid, $keep, $device, $tables, $schema );
630 }
631 }
632 }
633
634 /**
635 * Performs an unattended data backup (export)
636 *
637 * @param string $backupid Unique ID that identifies a data backup.
638 * @param integer $keep Number of backup files to be kept.
639 * @param string $device Location where export file is stored.
640 * @param array $tables Tables to be exported.
641 * @param array $schema Database schema name or remote database connection string.
642 */
643 protected function wpda_data_backup_run( $backupid, $keep, $device, $tables, $schema ) {
644 try {
645 $prefix = "wpda-data-backup-$backupid-";
646 $filename = $prefix . gmdate( 'YmdHis' ) . '.sql';
647
648 if ( 'local_path' === $device ) {
649 $local_path = WPDA::get_option( WPDA::OPTION_DB_LOCAL_PATH );
650 $client_file_name = $local_path . $filename;
651 $file = fopen( $client_file_name, 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fopen
652 $wpda_export = new WPDA_Export_Sql();
653 $wpda_export->set_output_stream( $file );
654 $wpda_export->export_with_arguments(
655 'on',
656 'on',
657 'on',
658 $schema,
659 $tables,
660 'table'
661 );
662 fclose( $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose
663 $keep_counting = 0;
664 $files_sorted = array();
665 foreach ( glob( $local_path . "wpda-data-backup-$backupid-*.sql" ) as $filename ) {
666 array_push( $files_sorted, $filename );//phpcs:ignore - 8.1 proof
667 }
668 rsort( $files_sorted );//phpcs:ignore - 8.1 proof
669 foreach ( $files_sorted as $file ) {
670 $keep_counting ++;
671 if ( $keep_counting > (int) $keep ) {
672 unlink( $file );
673 }
674 }
675 } elseif ( 'dropbox' === $device ) {
676 // To use a stream for Dropbox we first need to write the export to a temporary file.
677 $temporary_file = tmpfile();
678 $wpda_export = new WPDA_Export_Sql();
679 $wpda_export->set_output_stream( $temporary_file );
680 $wpda_export->export_with_arguments(
681 'on',
682 'on',
683 'on',
684 $schema,
685 $tables,
686 'table'
687 );
688
689 $client_access_token = WPDA_Settings_DataBackup::dropbox_get_token();
690 if ( false === $client_access_token ) {
691 // Use old token strategy (for older activations).
692 $client_access_token = get_option( 'wpda_db_dropbox_access_token' );
693 if ( false === $client_access_token ) {
694 // No token = no dropbox backup.
695 WPDA::log( $backupid, 'ERROR', "Data backup '$backupid'' failed (missing access token)" );
696 return;
697 }
698 }
699
700 $client_access_path = WPDA::get_option( WPDA::OPTION_DB_DROPBOX_PATH );
701 if ( '' === $client_access_path ) {
702 $client_access_path = '/';
703 }
704 $client_file_name = $client_access_path . $filename;
705 $post_max_size = WPDA_Remote_Call::max_size();
706
707 if (
708 $post_max_size < filesize( stream_get_meta_data( $temporary_file )['uri'] ) &&
709 ! extension_loaded('zip')
710 ) {
711 // File is too big to send in one chunk and zip archive is not installed.
712 WPDA::log( $backupid, 'ERROR', "Data backup '$backupid'' failed (ZipArchive not installed)" );
713 return;
714 }
715
716 if ( extension_loaded('zip') ) {
717 $zip = new \ZipArchive();
718 $zipfile = sys_get_temp_dir() . '/' . $filename . '.zip';
719 if ( ! $zip->open( $zipfile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE ) ) {
720 WPDA::log( $backupid, 'ERROR', "Data backup '$backupid'' failed (could not create ZIP file)" );
721 return;
722 }
723 $zip->addFile( stream_get_meta_data( $temporary_file )['uri'], $filename );
724 $zip->close();
725
726 $zpf = fopen( $zipfile, 'r' );
727 WPDA_Remote_Call::post(
728 'https://content.dropboxapi.com/2/files/upload',
729 fread( $zpf, filesize( $zipfile ) ),
730 false,
731 array(
732 'Authorization' => "Bearer $client_access_token",
733 'Content-Type' => 'application/octet-stream',
734 'Dropbox-API-Arg' => '{"path":"' . $client_file_name . '.zip","mode":"add","autorename":false,"mute":false,"strict_conflict":false}',
735 )
736 );
737 } else {
738 fseek( $temporary_file, 0 );
739 WPDA_Remote_Call::post(
740 'https://content.dropboxapi.com/2/files/upload',
741 fread( $temporary_file, filesize( stream_get_meta_data( $temporary_file )['uri'] ) ),
742 false,
743 array(
744 'Authorization' => "Bearer $client_access_token",
745 'Content-Type' => 'application/octet-stream',
746 'Dropbox-API-Arg' => '{"path":"' . $client_file_name . '","mode":"add","autorename":false,"mute":false,"strict_conflict":false}',
747 )
748 );
749 }
750
751 // Search for outdated files.
752 $ext = extension_loaded('zip') ? '.zip' : '';
753 $response = WPDA_Remote_Call::post(
754 'https://api.dropboxapi.com/2/files/search_v2',
755 json_encode(
756 array(
757 'options' => array(
758 'file_status' => 'active',
759 'filename_only' => false,
760 'max_results' => 999,
761 'path' => substr( $client_access_path, 0, strlen( $client_access_path ) - 1 )
762 ),
763 'query' => $prefix . '*' . $ext,
764 )
765 ),
766 false,
767 array(
768 'Authorization' => "Bearer $client_access_token",
769 'Content-Type' => 'application/json',
770 )
771 );
772
773 if ( 'ALL' !== $keep && isset( $response['body'] ) ) {
774 $body_content = json_decode( $response['body'], true );
775 if ( isset( $body_content['matches'] ) ) {
776 $keep_counting = 0;
777 $files_sorted = array();
778 foreach ( $body_content['matches'] as $match ) {
779 array_push( $files_sorted, $match['metadata']['metadata']['name'] );//phpcs:ignore - 8.1 proof
780 }
781 rsort( $files_sorted );//phpcs:ignore - 8.1 proof
782 foreach ( $files_sorted as $file ) {
783 $keep_counting++;
784 if ( $keep_counting > (int) $keep ) {
785 // Remove outdated files.
786 WPDA_Remote_Call::post(
787 'https://api.dropboxapi.com/2/files/delete_v2',
788 json_encode(
789 array(
790 'path' => $client_access_path . $file,
791 )
792 ),
793 false,
794 array(
795 'Authorization' => "Bearer $client_access_token",
796 'Content-Type' => 'application/json',
797 )
798 );
799 }
800 }
801 }
802 }
803 }
804 } catch ( Exception $e ) {
805 WPDA::log( $backupid, 'ERROR', "Data backup '$backupid' failed: " . $e->getMessage() );
806 }
807
808 WPDA::log( $backupid, 'INFO', "Data backup '$backupid' finished" );
809 }
810
811 /**
812 * Create a cron job for data export
813 *
814 * Backup ID = $_REQUEST['backupid']
815 */
816 public function wpda_add_cron_job() {
817 if ( ! isset( $_REQUEST['backupid'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
818 $this->show_wp_cron();
819 $msg = new WPDA_Message_Box(
820 array(
821 'message_text' => __( 'Mandatory item "backupid" not found', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
822 'message_type' => 'error',
823 'message_is_dismissible' => false,
824 )
825 );
826 $msg->box();
827
828 return;
829 }
830 $backupid = sanitize_text_field( wp_unslash( $_REQUEST['backupid'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
831 if ( ! isset( $_REQUEST['interval'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
832 $this->show_wp_cron();
833 $msg = new WPDA_Message_Box(
834 array(
835 'message_text' => __( 'Mandatory item "interval" not found', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
836 'message_type' => 'error',
837 'message_is_dismissible' => false,
838 )
839 );
840 $msg->box();
841
842 return;
843 }
844 $interval = sanitize_text_field( wp_unslash( $_REQUEST['interval'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
845 if ( ! isset( $_REQUEST['keep'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
846 $this->show_wp_cron();
847 $msg = new WPDA_Message_Box(
848 array(
849 'message_text' => __( 'Mandatory item "keep" not found', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
850 'message_type' => 'error',
851 'message_is_dismissible' => false,
852 )
853 );
854 $msg->box();
855
856 return;
857 }
858 $keep = sanitize_text_field( wp_unslash( $_REQUEST['keep'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
859 if ( ! isset( $_REQUEST['device'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
860 $this->show_wp_cron();
861 $msg = new WPDA_Message_Box(
862 array(
863 'message_text' => __( 'Mandatory item "device" not found', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
864 'message_type' => 'error',
865 'message_is_dismissible' => false,
866 )
867 );
868 $msg->box();
869
870 return;
871 }
872 $device = sanitize_text_field( wp_unslash( $_REQUEST['device'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
873 if ( ! isset( $_REQUEST['wpda_table_name_export'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
874 $this->show_wp_cron();
875 $msg = new WPDA_Message_Box(
876 array(
877 'message_text' => __( 'No tables defined to backup', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
878 'message_type' => 'error',
879 'message_is_dismissible' => false,
880 )
881 );
882 $msg->box();
883
884 return;
885 } else {
886 $request_tables = WPDA::sanitize_text_field_array( $_REQUEST['wpda_table_name_export'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput, WordPress.Security.NonceVerification
887 }
888 if ( isset( $_REQUEST['wpdaschema_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
889 $schema_name = sanitize_text_field( wp_unslash( $_REQUEST['wpdaschema_name'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
890 } else {
891 $schema_name = '';
892 }
893 if ( 'runonce' === $interval ) {
894 // Run data backup once. Do not create job.
895 $data_backups = get_option( 'wpda_data_backup_option_runonce' );
896 if ( ! $data_backups ) {
897 $data_backups = array();
898 }
899 $data_backup = array(
900 'id' => self::PREFIX_RUNONCE . $backupid,
901 'device' => $device,
902 'keep' => $keep,
903 'schema_name' => $schema_name,
904 'tables' => $request_tables,
905 );
906 array_push( $data_backups, $data_backup );//phpcs:ignore - 8.1 proof
907 if ( ! update_option( 'wpda_data_backup_option_runonce', $data_backups ) ) {
908 $msg = new WPDA_Message_Box(
909 array(
910 'message_text' => __( 'Could not create data backup', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
911 'message_type' => 'error',
912 'message_is_dismissible' => false,
913 )
914 );
915 $msg->box();
916 } else {
917 if ( ! wp_schedule_single_event(
918 current_time( 'timestamp' ), // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
919 'wpda_data_backup',
920 array( self::PREFIX_RUNONCE . $backupid )
921 )
922 ) {
923 $msg = new WPDA_Message_Box(
924 array(
925 'message_text' => __( 'Backup failed', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
926 'message_type' => 'error',
927 'message_is_dismissible' => false,
928 )
929 );
930 $msg->box();
931 }
932 }
933 ?>
934 <div class="wrap">
935 <h1 class="wp-heading-inline">
936 <?php echo __( 'Data Backup' ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
937 </h1>
938 <p><?php echo __( 'Data backup started. Please check backup location.' ); // phpcs:ignore WordPress.Security.EscapeOutput ?></p>
939 <p>
940 <a href="?page=wpda&page_action=wpda_backup" class="button">
941 <i class="fas fa-angle-left wpda_icon_on_button"></i>
942 <?php echo __( 'List' ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
943 </a>
944 </p>
945 </div>
946 <?php
947 } else {
948 // Create job for data backup.
949 $data_backups = get_option( 'wpda_data_backup_option' );
950 if ( ! $data_backups ) {
951 $data_backups = array();
952 } else {
953 foreach ( $data_backups as $data_backup ) {
954 if ( $data_backup['id'] === $backupid ) {
955 $this->show_wp_cron();
956 $msg = new WPDA_Message_Box(
957 array(
958 'message_text' => __( 'Backup id already exists', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
959 'message_type' => 'error',
960 'message_is_dismissible' => false,
961 )
962 );
963 $msg->box();
964
965 return;
966 }
967 }
968 }
969 $data_backup = array(
970 'id' => $backupid,
971 'device' => $device,
972 'keep' => $keep,
973 'schema_name' => $schema_name,
974 'tables' => $request_tables,
975 );
976 array_push( $data_backups, $data_backup );//phpcs:ignore - 8.1 proof
977 if ( ! update_option( 'wpda_data_backup_option', $data_backups ) ) {
978 $this->show_wp_cron();
979 $msg = new WPDA_Message_Box(
980 array(
981 'message_text' => __( 'Could not save data backup options', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
982 'message_type' => 'error',
983 'message_is_dismissible' => false,
984 )
985 );
986 $msg->box();
987 } else {
988 global $wpdb;
989 $wpdb->flush();
990 wp_cache_flush();
991 if ( ! wp_next_scheduled( 'wpda_data_backup', array( $backupid ) ) ) {
992 wp_schedule_event( current_time( 'timestamp' ), $interval, 'wpda_data_backup', array( $backupid ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
993 }
994 }
995 $this->show_wp_cron();
996 }
997 }
998
999 /**
1000 * Remove a data backup from cron
1001 *
1002 * Backup ID = $_REQUEST['schedule_args']
1003 */
1004 public function wpda_remove_cron_job() {
1005 if ( isset( $_REQUEST['schedule_args'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1006 $backupid = sanitize_text_field( wp_unslash( $_REQUEST['schedule_args'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1007 if ( isset( $_REQUEST['schedule'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1008 $schedule = sanitize_text_field( wp_unslash( $_REQUEST['schedule'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1009 if ( '' !== $backupid ) {
1010 $timestamp = wp_next_scheduled( $schedule, array( $backupid ) );
1011 $unschedule = wp_unschedule_event( $timestamp, $schedule, array( $backupid ) );
1012 } else {
1013 $timestamp = wp_next_scheduled( $schedule );
1014 $unschedule = wp_unschedule_event( $timestamp, $schedule );
1015 }
1016
1017 if ( false === $unschedule ) {
1018 $msg = new WPDA_Message_Box(
1019 array(
1020 'message_text' => __( 'Could not delete data backup schedule', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
1021 'message_type' => 'error',
1022 'message_is_dismissible' => false,
1023 )
1024 );
1025 $msg->box();
1026 } else {
1027 $msg = new WPDA_Message_Box(
1028 array(
1029 'message_text' => __( 'Deleted data backup schedule', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
1030 )
1031 );
1032 $msg->box();
1033 // Remove job from queue.
1034 $data_backups = get_option( 'wpda_data_backup_option' );
1035 $data_backups_new = array();
1036 foreach ( $data_backups as $data_backup ) {
1037 if ( $data_backup['id'] !== $backupid ) {
1038 array_push( $data_backups_new, $data_backup );//phpcs:ignore - 8.1 proof
1039 }
1040 }
1041 update_option( 'wpda_data_backup_option', $data_backups_new );
1042 }
1043 }
1044 }
1045 $this->show_wp_cron();
1046 }
1047
1048 /**
1049 * Update a data backup
1050 *
1051 * Backup ID = $_REQUEST['backupid']
1052 */
1053 public function wpda_update_cron_job() {
1054 if ( isset( $_REQUEST['backupid'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1055 $backupid = sanitize_text_field( wp_unslash( $_REQUEST['backupid'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1056 } else {
1057 $msg = new WPDA_Message_Box(
1058 array(
1059 'message_text' => __( 'Mandatory item "backupid" not found', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
1060 'message_type' => 'error',
1061 'message_is_dismissible' => false,
1062 )
1063 );
1064 $msg->box();
1065 }
1066 if ( isset( $_REQUEST['wpda_table_name_export'] ) && is_array( $_REQUEST['wpda_table_name_export'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1067 $wpda_table_name_export = WPDA::sanitize_text_field_array( $_REQUEST['wpda_table_name_export'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput ,WordPress.Security.NonceVerification
1068 } else {
1069 $msg = new WPDA_Message_Box(
1070 array(
1071 'message_text' => __( 'No tables defined to backup', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
1072 'message_type' => 'error',
1073 'message_is_dismissible' => false,
1074 )
1075 );
1076 $msg->box();
1077 }
1078 if ( isset( $_REQUEST['interval'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1079 $interval = sanitize_text_field( wp_unslash( $_REQUEST['interval'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1080 } else {
1081 $msg = new WPDA_Message_Box(
1082 array(
1083 'message_text' => __( 'Mandatory item "interval" not found', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
1084 'message_type' => 'error',
1085 'message_is_dismissible' => false,
1086 )
1087 );
1088 $msg->box();
1089 }
1090 if ( isset( $_REQUEST['keep'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1091 $keep = sanitize_text_field( wp_unslash( $_REQUEST['keep'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1092 } else {
1093 $msg = new WPDA_Message_Box(
1094 array(
1095 'message_text' => __( 'Mandatory item "keep" not found', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
1096 'message_type' => 'error',
1097 'message_is_dismissible' => false,
1098 )
1099 );
1100 $msg->box();
1101 }
1102 if ( isset( $_REQUEST['device'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1103 $device = sanitize_text_field( wp_unslash( $_REQUEST['device'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1104 } else {
1105 $msg = new WPDA_Message_Box(
1106 array(
1107 'message_text' => __( 'Mandatory item "device" not found', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
1108 'message_type' => 'error',
1109 'message_is_dismissible' => false,
1110 )
1111 );
1112 $msg->box();
1113 }
1114 if ( isset( $_REQUEST['wpdaschema_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1115 $schema_name = sanitize_text_field( wp_unslash( $_REQUEST['wpdaschema_name'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1116 } else {
1117 $schema_name = '';
1118 }
1119 // Reschedule current job.
1120 $timestamp = wp_next_scheduled( 'wpda_data_backup', array( $backupid ) );
1121 if ( false === wp_unschedule_event( $timestamp, 'wpda_data_backup', array( $backupid ) ) ) {
1122 $msg = new WPDA_Message_Box(
1123 array(
1124 'message_text' => __( 'Could not delete data backup schedule', 'wp-data-access' ), // phpcs:ignore WordPress.Security.EscapeOutput
1125 'message_type' => 'error',
1126 'message_is_dismissible' => false,
1127 )
1128 );
1129 $msg->box();
1130 } else {
1131 // Update job settings.
1132 $data_backups = get_option( 'wpda_data_backup_option' );
1133 $data_backups_new = array();
1134 foreach ( $data_backups as $data_backup ) {
1135 if ( $data_backup['id'] !== $backupid ) {
1136 array_push( $data_backups_new, $data_backup );//phpcs:ignore - 8.1 proof
1137 } else {
1138 $data_backup_updated = array(
1139 'id' => $backupid,
1140 'keep' => $keep,
1141 'device' => $device,
1142 'schema_name' => $schema_name,
1143 'tables' => $wpda_table_name_export,
1144 );
1145 array_push( $data_backups_new, $data_backup_updated );//phpcs:ignore - 8.1 proof
1146 }
1147 }
1148 update_option( 'wpda_data_backup_option', $data_backups_new );
1149 // Reschedule job with new arguments.
1150 wp_schedule_event( current_time( 'timestamp' ), $interval, 'wpda_data_backup', array( $backupid ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
1151 }
1152 $this->show_wp_cron();
1153 }
1154
1155 private function get_wp_nonce() {
1156 return wp_create_nonce( 'wpda-backup-' . WPDA::get_current_user_login() );
1157 }
1158
1159 }
1160
1161 }
1162