BackUpWordPress - Version 2.6

Version Description

Download this release

Release Info

Developer willmot
Plugin Icon 128x128 BackUpWordPress
Version 2.6
Comparing to
See all releases

Code changes from version 2.5 to 2.6

admin/actions.php CHANGED
@@ -14,7 +14,7 @@ function hmbkp_request_delete_backup() {
14
  $deleted = $schedule->delete_backup( sanitize_text_field( base64_decode( $_GET['hmbkp_delete_backup'] ) ) );
15
 
16
  if ( is_wp_error( $deleted ) )
17
- echo $deleted->get_error_message();
18
 
19
  wp_safe_redirect( remove_query_arg( array( 'hmbkp_delete_backup', '_wpnonce' ) ), 303 );
20
 
@@ -67,7 +67,7 @@ function hmbkp_ajax_request_do_backup() {
67
 
68
  check_ajax_referer( 'hmbkp_nonce', 'nonce' );
69
 
70
- // Fixes an issue on servers which only allow a single session per client
71
  session_write_close();
72
 
73
  if ( empty( $_POST['hmbkp_schedule_id'] ) )
@@ -158,6 +158,9 @@ function hmbkp_request_cancel_backup() {
158
  if ( $schedule->get_running_backup_filename() && file_exists( trailingslashit( hmbkp_path() ) . $schedule->get_running_backup_filename() ) )
159
  unlink( trailingslashit( hmbkp_path() ) . $schedule->get_running_backup_filename() );
160
 
 
 
 
161
  hmbkp_cleanup();
162
 
163
  wp_safe_redirect( remove_query_arg( array( 'action' ) ), 303 );
@@ -250,13 +253,13 @@ function hmbkp_ajax_cron_test() {
250
 
251
  if ( is_wp_error( $response ) ) {
252
 
253
- echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( '%1$s is returning a %2$s response which could mean cron jobs aren\'t getting fired properly. BackUpWordPress relies on wp-cron to run scheduled back ups. See the %3$s for more details.', 'hmbkp' ), '<code>wp-cron.php</code>', '<code>' . $response->get_error_message() . '</code>', '<a href="http://wordpress.org/extend/plugins/backupwordpress/faq/">FAQ</a>' ) . '</p></div>';
254
 
255
  update_option( 'hmbkp_wp_cron_test_failed', true );
256
 
257
  } elseif ( wp_remote_retrieve_response_code( $response ) != 200 ) {
258
 
259
- echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( '%1$s is returning a %2$s response which could mean cron jobs aren\'t getting fired properly. BackUpWordPress relies on wp-cron to run scheduled back ups. See the %3$s for more details.', 'hmbkp' ), '<code>wp-cron.php</code>', '<code>' . esc_html( wp_remote_retrieve_response_code( $response ) ) . ' ' . esc_html( get_status_header_desc( wp_remote_retrieve_response_code( $response ) ) ) . '</code>', '<a href="http://wordpress.org/extend/plugins/backupwordpress/faq/">FAQ</a>' ) . '</p></div>';
260
 
261
  update_option( 'hmbkp_wp_cron_test_failed', true );
262
 
@@ -327,7 +330,7 @@ add_action( 'wp_ajax_hmbkp_add_schedule_load', 'hmbkp_add_schedule_load' );
327
  *
328
  * Validate and either return errors or update the schedule
329
  */
330
- function hmnkp_edit_schedule_submit() {
331
 
332
  if ( empty( $_GET['hmbkp_schedule_id'] ) )
333
  die;
@@ -336,71 +339,160 @@ function hmnkp_edit_schedule_submit() {
336
 
337
  $errors = array();
338
 
 
 
339
 
340
- if ( isset( $_GET['hmbkp_schedule_type'] ) ) {
 
 
341
 
342
- $schedule_type = sanitize_text_field( $_GET['hmbkp_schedule_type'] );
343
 
344
- if ( ! trim( $schedule_type ) )
345
- $errors['hmbkp_schedule_type'] = __( 'Backup type cannot be empty', 'hmbkp' );
 
 
346
 
347
- elseif ( ! in_array( $schedule_type, array( 'complete', 'file', 'database' ) ) )
348
- $errors['hmbkp_schedule_type'] = __( 'Invalid backup type', 'hmbkp' );
349
 
350
- else
351
- $schedule->set_type( $schedule_type );
352
 
353
- }
354
 
355
- if ( isset( $_GET['hmbkp_schedule_reoccurrence'] ) ) {
356
 
357
- $schedule_reoccurrence = sanitize_text_field( $_GET['hmbkp_schedule_reoccurrence'] );
358
 
359
- if ( empty( $schedule_reoccurrence ) )
360
- $errors['hmbkp_schedule_reoccurrence'] = __( 'Schedule cannot be empty', 'hmbkp' );
361
 
362
- elseif ( ! in_array( $schedule_reoccurrence, array_keys( $schedule->get_cron_schedules() ) ) && $schedule_reoccurrence !== 'manually' )
363
- $errors['hmbkp_schedule_reoccurrence'] = __( 'Invalid schedule', 'hmbkp' );
364
 
365
- else
366
- $schedule->set_reoccurrence( $schedule_reoccurrence );
367
 
368
- }
 
369
 
370
- if ( isset( $_GET['hmbkp_schedule_max_backups'] ) ) {
371
 
372
- $schedule_max_backups = sanitize_text_field( $_GET['hmbkp_schedule_max_backups'] );
 
373
 
374
- if ( empty( $schedule_max_backups ) )
375
- $errors['hmbkp_schedule_max_backups'] = __( 'Max backups can\'t be empty', 'hmbkp' );
376
 
377
- elseif ( ! is_numeric( $schedule_max_backups ) )
378
- $errors['hmbkp_schedule_max_backups'] = __( 'Max backups must be a number', 'hmbkp' );
379
 
380
- elseif ( ! ( $schedule_max_backups >= 1 ) )
381
- $errors['hmbkp_schedule_max_backups'] = __( 'Max backups must be greater than 0', 'hmbkp' );
382
 
383
- else
384
- $schedule->set_max_backups( (int) $schedule_max_backups );
385
 
386
- // Remove any old backups in-case max backups was reduced
387
- $schedule->delete_old_backups();
388
 
389
- }
390
 
391
- // Save the service options
392
- foreach ( HMBKP_Services::get_services( $schedule ) as $service )
393
- $errors = array_merge( $errors, $service->save() );
394
 
395
- $schedule->save();
396
 
397
- if ( $errors )
398
- echo json_encode( $errors );
399
 
400
- die;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
 
402
  }
403
- add_action( 'wp_ajax_hmnkp_edit_schedule_submit', 'hmnkp_edit_schedule_submit' );
404
 
405
  /**
406
  * Add an exclude rule
@@ -552,7 +644,7 @@ add_action( 'wp_ajax_hmbkp_email_error', 'hmbkp_send_error_via_email' );
552
  *
553
  * @return void
554
  */
555
- function hmbkp_load_enable_support () {
556
 
557
  check_ajax_referer( 'hmbkp_nonce', '_wpnonce' );
558
 
14
  $deleted = $schedule->delete_backup( sanitize_text_field( base64_decode( $_GET['hmbkp_delete_backup'] ) ) );
15
 
16
  if ( is_wp_error( $deleted ) )
17
+ wp_die( $deleted->get_error_message() );
18
 
19
  wp_safe_redirect( remove_query_arg( array( 'hmbkp_delete_backup', '_wpnonce' ) ), 303 );
20
 
67
 
68
  check_ajax_referer( 'hmbkp_nonce', 'nonce' );
69
 
70
+ // Fixes an issue on servers which only allow a single session per client
71
  session_write_close();
72
 
73
  if ( empty( $_POST['hmbkp_schedule_id'] ) )
158
  if ( $schedule->get_running_backup_filename() && file_exists( trailingslashit( hmbkp_path() ) . $schedule->get_running_backup_filename() ) )
159
  unlink( trailingslashit( hmbkp_path() ) . $schedule->get_running_backup_filename() );
160
 
161
+ if ( $schedule->get_schedule_running_path() && file_exists( $schedule->get_schedule_running_path() ) )
162
+ unlink( $schedule->get_schedule_running_path() );
163
+
164
  hmbkp_cleanup();
165
 
166
  wp_safe_redirect( remove_query_arg( array( 'action' ) ), 303 );
253
 
254
  if ( is_wp_error( $response ) ) {
255
 
256
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( '%1$s is returning a %2$s response which could mean cron jobs aren\'t getting fired properly. BackUpWordPress relies on wp-cron to run scheduled backups. See the %3$s for more details.', 'hmbkp' ), '<code>wp-cron.php</code>', '<code>' . $response->get_error_message() . '</code>', '<a href="http://wordpress.org/extend/plugins/backupwordpress/faq/">FAQ</a>' ) . '</p></div>';
257
 
258
  update_option( 'hmbkp_wp_cron_test_failed', true );
259
 
260
  } elseif ( wp_remote_retrieve_response_code( $response ) != 200 ) {
261
 
262
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( '%1$s is returning a %2$s response which could mean cron jobs aren\'t getting fired properly. BackUpWordPress relies on wp-cron to run scheduled backups. See the %3$s for more details.', 'hmbkp' ), '<code>wp-cron.php</code>', '<code>' . esc_html( wp_remote_retrieve_response_code( $response ) ) . ' ' . esc_html( get_status_header_desc( wp_remote_retrieve_response_code( $response ) ) ) . '</code>', '<a href="http://wordpress.org/extend/plugins/backupwordpress/faq/">FAQ</a>' ) . '</p></div>';
263
 
264
  update_option( 'hmbkp_wp_cron_test_failed', true );
265
 
330
  *
331
  * Validate and either return errors or update the schedule
332
  */
333
+ function hmbkp_edit_schedule_submit() {
334
 
335
  if ( empty( $_GET['hmbkp_schedule_id'] ) )
336
  die;
339
 
340
  $errors = array();
341
 
342
+ // called from an extension
343
+ if ( isset( $_GET['is_destination_form'] ) ) {
344
 
345
+ // Save the service options
346
+ foreach ( HMBKP_Services::get_services( $schedule ) as $service )
347
+ $errors = array_merge( $errors, $service->save() );
348
 
349
+ $schedule->save();
350
 
351
+ if ( empty( $errors ) )
352
+ wp_send_json_success();
353
+ else
354
+ wp_send_json_error( $errors );
355
 
356
+ } else {
 
357
 
358
+ $schedule_settings = array();
 
359
 
360
+ if ( isset( $_GET['hmbkp_schedule_recurrence'] ) ) {
361
 
362
+ $hmbkp_schedule_recurrence = $_GET['hmbkp_schedule_recurrence'];
363
 
364
+ if ( isset( $_GET['hmbkp_schedule_type'] ) ) {
365
 
366
+ $schedule_type = sanitize_text_field( $_GET['hmbkp_schedule_type'] );
 
367
 
368
+ if ( ! trim( $schedule_type ) )
369
+ $errors['hmbkp_schedule_type'] = __( 'Backup type cannot be empty', 'hmbkp' );
370
 
371
+ elseif ( ! in_array( $schedule_type, array( 'complete', 'file', 'database' ) ) )
372
+ $errors['hmbkp_schedule_type'] = __( 'Invalid backup type', 'hmbkp' );
373
 
374
+ else
375
+ $schedule_settings['schedule_type'] = $schedule_type;
376
 
377
+ }
378
 
379
+ if ( isset( $_GET['hmbkp_schedule_recurrence']['hmbkp_type'] ) ) {
380
+ $hmbkp_schedule_recurrence_type = sanitize_text_field( $_GET['hmbkp_schedule_recurrence']['hmbkp_type'] );
381
 
382
+ if ( empty( $hmbkp_schedule_recurrence_type ) )
383
+ $errors['hmbkp_schedule_recurrence']['hmbkp_type'] = __( 'Schedule cannot be empty', 'hmbkp' );
384
 
385
+ elseif ( ! in_array( $hmbkp_schedule_recurrence_type, array_keys( hmbkp_get_cron_schedules() ) ) && $hmbkp_schedule_recurrence_type !== 'manually' )
386
+ $errors['hmbkp_schedule_recurrence']['hmbkp_type'] = __( 'Invalid schedule', 'hmbkp' );
387
 
388
+ }
 
389
 
390
+ if ( 'manually' !== $hmbkp_schedule_recurrence_type ) {
 
391
 
392
+ if ( isset( $_GET['hmbkp_schedule_recurrence']['hmbkp_schedule_start_day_of_week'] ) ) {
 
393
 
394
+ $hmbkp_schedule_time['day_of_week'] = sanitize_text_field( $_GET['hmbkp_schedule_recurrence']['hmbkp_schedule_start_day_of_week'] );
395
 
396
+ if ( ! in_array( $hmbkp_schedule_time['day_of_week'], array( 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ) ) )
397
+ $errors['hmbkp_schedule_start_day_of_week'] = __( 'Day of week must be an integer between 1 and 7', 'backupwordpress' );
 
398
 
399
+ }
400
 
401
+ if ( isset( $_GET['hmbkp_schedule_recurrence']['hmbkp_schedule_start_day_of_month'] ) ) {
 
402
 
403
+ $hmbkp_schedule_time['day_of_month'] = absint( $_GET['hmbkp_schedule_recurrence']['hmbkp_schedule_start_day_of_month'] );
404
+
405
+ $options = array(
406
+ 'min_range' => 1,
407
+ 'max_range' => 31
408
+ );
409
+
410
+ if ( false === filter_var( $hmbkp_schedule_time['day_of_month'], FILTER_VALIDATE_INT, array( 'options' => $options ) ) )
411
+ $errors['hmbkp_schedule_start_day_of_month'] = __( 'Day of month must be between 1 and 31', 'backupwordpress' );
412
+
413
+ }
414
+
415
+ if ( isset( $_GET['hmbkp_schedule_recurrence']['hmbkp_schedule_start_hours'] ) ) {
416
+
417
+ $hmbkp_schedule_time['hours'] = absint( $_GET['hmbkp_schedule_recurrence']['hmbkp_schedule_start_hours'] );
418
+
419
+ $options = array(
420
+ 'min_range' => 1,
421
+ 'max_range' => 23
422
+ );
423
+
424
+ if ( false === filter_var( $hmbkp_schedule_time['hours'], FILTER_VALIDATE_INT, array( 'options' => $options ) ) )
425
+ $errors['hmbkp_schedule_start_hours'] = __( 'Hours must be between 1 and 23', 'backupwordpress' );
426
+
427
+ }
428
+
429
+ if ( isset( $_GET['hmbkp_schedule_recurrence']['hmbkp_schedule_start_minutes'] ) ) {
430
+
431
+ $hmbkp_schedule_time['minutes'] = absint( $_GET['hmbkp_schedule_recurrence']['hmbkp_schedule_start_minutes'] );
432
+
433
+ $options = array(
434
+ 'min_range' => 0,
435
+ 'max_range' => 59
436
+ );
437
+
438
+ if ( false === filter_var( $hmbkp_schedule_time['minutes'], FILTER_VALIDATE_INT, array( 'options' => $options ) ) )
439
+ $errors['hmbkp_schedule_start_minutes'] = __( 'Minutes must be between 0 and 59', 'backupwordpress' );
440
+
441
+ }
442
+
443
+ }
444
+ }
445
+
446
+ if ( isset( $_GET['hmbkp_schedule_max_backups'] ) ) {
447
+
448
+ $schedule_max_backups = sanitize_text_field( $_GET['hmbkp_schedule_max_backups'] );
449
+
450
+ if ( empty( $schedule_max_backups ) )
451
+ $errors['hmbkp_schedule_max_backups'] = __( 'Max backups can\'t be empty', 'hmbkp' );
452
+
453
+ elseif ( ! is_numeric( $schedule_max_backups ) )
454
+ $errors['hmbkp_schedule_max_backups'] = __( 'Max backups must be a number', 'hmbkp' );
455
+
456
+ elseif ( ! ( $schedule_max_backups >= 1 ) )
457
+ $errors['hmbkp_schedule_max_backups'] = __( 'Max backups must be greater than 0', 'hmbkp' );
458
+
459
+ else
460
+ $schedule_settings['schedule_max_backups'] = absint( $schedule_max_backups );
461
+
462
+ }
463
+
464
+ // Save the service options
465
+ foreach ( HMBKP_Services::get_services( $schedule ) as $service ) {
466
+ $errors = array_merge( $errors, $service->save() );
467
+ }
468
+
469
+ if ( $errors ) {
470
+ wp_send_json_error( $errors );
471
+
472
+ } else {
473
+
474
+ if ( isset( $hmbkp_schedule_time ) )
475
+ $schedule->set_schedule_start_time( hmbkp_determine_start_time( $hmbkp_schedule_recurrence_type, $hmbkp_schedule_time ) );
476
+
477
+ $schedule->set_reoccurrence( $hmbkp_schedule_recurrence_type );
478
+ $schedule->set_type( $schedule_type );
479
+ $schedule->set_max_backups( $schedule_settings['schedule_max_backups'] );
480
+
481
+ $schedule->save();
482
+
483
+ // Remove any old backups in-case max backups was reduced
484
+ $schedule->delete_old_backups();
485
+
486
+ wp_send_json_success();
487
+
488
+ }
489
+
490
+ }
491
+
492
+ die();
493
 
494
  }
495
+ add_action( 'wp_ajax_hmbkp_edit_schedule_submit', 'hmbkp_edit_schedule_submit' );
496
 
497
  /**
498
  * Add an exclude rule
644
  *
645
  * @return void
646
  */
647
+ function hmbkp_load_enable_support() {
648
 
649
  check_ajax_referer( 'hmbkp_nonce', '_wpnonce' );
650
 
admin/backups.php CHANGED
@@ -37,7 +37,7 @@
37
 
38
  <?php endforeach; ?>
39
 
40
- <li><a class="colorbox" href="<?php esc_attr_e( esc_url( add_query_arg( array( 'action' => 'hmbkp_add_schedule_load' ), is_multisite() ? admin_url( 'admin-ajax.php' ) : network_admin_url( 'admin-ajax.php' ) ) ) ); ?>"> + <?php _e( 'add schedule', 'hmbkp' ); ?></a></li>
41
 
42
  </ul>
43
 
37
 
38
  <?php endforeach; ?>
39
 
40
+ <li><a class="colorbox" href="<?php esc_attr_e( esc_url( add_query_arg( array( 'action' => 'hmbkp_add_schedule_load' ), is_multisite() ? network_admin_url( 'admin-ajax.php' ) : admin_url( 'admin-ajax.php' ) ) ) ); ?>"> + <?php _e( 'add schedule', 'hmbkp' ); ?></a></li>
41
 
42
  </ul>
43
 
admin/constants.php CHANGED
@@ -1,35 +1,124 @@
1
  <div id="hmbkp-constants">
2
 
3
- <p><?php printf( __( 'You can %1$s any of the following %2$s in your %3$s to control advanced settings. %4$s. Defined %5$s will be highlighted.', 'hmbkp' ), '<code>define</code>', '<code>' . __( 'Constants', 'hmbkp' ) . '</code>', '<code>wp-config.php</code>', '<a href="http://codex.wordpress.org/Editing_wp-config.php">' . __( 'The Codex can help', 'hmbkp' ) . '</a>', '<code>' . __( 'Constants', 'hmbkp' ) . '</code>' ); ?></p>
4
 
5
- <dl>
6
 
7
- <dt<?php if ( defined( 'HMBKP_PATH' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_PATH</code></dt>
8
- <dd><p><?php printf( __( 'The path to folder you would like to store your backup files in, defaults to %s.', 'hmbkp' ), '<code>' . esc_html( hmbkp_path_default() ) . '</code>' ); ?></p><p class="example"><?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_PATH', '/home/willmot/backups' );</code></p></dd>
9
 
10
- <dt<?php if ( defined( 'HMBKP_MYSQLDUMP_PATH' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_MYSQLDUMP_PATH</code></dt>
11
- <dd><p><?php printf( __( 'The path to your %1$s executable. Will be used for the %2$s part of the back up if available.', 'hmbkp' ), '<code>mysqldump</code>', '<code>' . __( 'database', 'hmbkp' ) . '</code>' ); ?></p><p class="example"><?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_MYSQLDUMP_PATH', '/opt/local/bin/mysqldump' );</code></p></dd>
12
 
13
- <dt<?php if ( defined( 'HMBKP_ZIP_PATH' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_ZIP_PATH</code></dt>
14
- <dd><p><?php printf( __( 'The path to your %1$s executable. Will be used to zip up your %2$s and %3$s if available.', 'hmbkp' ), '<code>zip</code>', '<code>' . __( 'files', 'hmbkp' ) . '</code>', '<code>' . __( 'database', 'hmbkp' ) . '</code>' ); ?><p class="example"><?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_ZIP_PATH', '/opt/local/bin/zip' );</code></p></dd>
15
 
16
- <dt<?php if ( defined( 'HMBKP_EXCLUDE' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_EXCLUDE</code></dt>
17
- <dd><p><?php _e( 'Comma separated list of files or directories to exclude, the backups directory is automatically excluded.', 'hmbkp' ); ?><p class="example"><?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_EXCLUDE', '/wp-content/uploads/, /stats/, .svn/, *.txt' );</code></p></dd>
 
18
 
19
- <dt<?php if ( defined( 'HMBKP_CAPABILITY' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_CAPABILITY</code></dt>
20
- <dd><p><?php printf( __( 'The capability to use when calling %1$s. Defaults to %2$s.', 'hmbkp' ), '<code>add_menu_page</code>', '<code>manage_options</code>' ); ?><p class="example"><?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_CAPABILITY', 'edit_posts' );</code></p></dd>
21
 
22
- <dt<?php if ( defined( 'HMBKP_ROOT' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_ROOT</code></dt>
23
- <dd><p><?php printf( __( 'The root directory that is backed up. Defaults to %s.', 'hmbkp' ), '<code>' . HM_Backup::get_home_path() . '</code>' ); ?><p class="example"><?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_ROOT', ABSPATH . 'wp/' );</code></p></dd>
24
 
25
- <dt<?php if ( defined( 'HMBKP_SCHEDULE_TIME' ) && HMBKP_SCHEDULE_TIME !== '11pm' ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_SCHEDULE_TIME</code></dt>
26
- <dd><p><?php printf( __( 'The time that your schedules should run. Defaults to %s.', 'hmbkp' ), '<code>23:00</code>' ); ?><p class="example"><?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_SCHEDULE_TIME', '07:30' );</code></p></dd>
27
 
28
- <?php
29
 
30
- foreach ( HMBKP_Services::get_services() as $file => $service )
31
- echo wp_kses_post( call_user_func( array( $service, 'constant' ) ) ); ?>
32
 
33
- </dl>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  </div>
1
  <div id="hmbkp-constants">
2
 
3
+ <p><?php printf( __( 'You can %1$s any of the following %2$s in your %3$s to control advanced settings. %4$s. Defined %5$s will be highlighted.', 'hmbkp' ), '<code>define</code>', '<code>' . __( 'Constants', 'hmbkp' ) . '</code>', '<code>wp-config.php</code>', '<a href="http://codex.wordpress.org/Editing_wp-config.php">' . __( 'The Codex can help', 'hmbkp' ) . '</a>', '<code>' . __( 'Constants', 'hmbkp' ) . '</code>' ); ?></p>
4
 
5
+ <table class="widefat">
6
 
7
+ <tr<?php if ( defined( 'HMBKP_PATH' ) ) { ?> class="hmbkp_active"<?php } ?>>
 
8
 
9
+ <td><code>HMBKP_PATH</code></td>
 
10
 
11
+ <td>
 
12
 
13
+ <?php if ( defined( 'HMBKP_PATH' ) ) { ?>
14
+ <p><?php printf( __( 'You\'ve set it to: %s', 'hmbkp' ), '<code>' . HMBKP_PATH . '</code>' ); ?></p>
15
+ <?php } ?>
16
 
17
+ <p><?php printf( __( 'The path to folder you would like to store your backup files in, defaults to %s.', 'hmbkp' ), '<code>' . esc_html( hmbkp_path_default() ) . '</code>' ); ?> <?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_PATH', '/home/willmot/backups' );</code></p>
 
18
 
19
+ </td>
 
20
 
21
+ </tr>
 
22
 
23
+ <tr<?php if ( defined( 'HMBKP_MYSQLDUMP_PATH' ) ) { ?> class="hmbkp_active"<?php } ?>>
24
 
25
+ <td><code>HMBKP_MYSQLDUMP_PATH</code></td>
 
26
 
27
+ <td>
28
+
29
+ <?php if ( defined( 'HMBKP_MYSQLDUMP_PATH' ) ) { ?>
30
+ <p><?php printf( __( 'You\'ve set it to: %s', 'hmbkp' ), '<code>' . HMBKP_MYSQLDUMP_PATH . '</code>' ); ?></p>
31
+ <?php } ?>
32
+
33
+ <p><?php printf( __( 'The path to your %1$s executable. Will be used for the %2$s part of the back up if available.', 'hmbkp' ), '<code>mysqldump</code>', '<code>' . __( 'database', 'hmbkp' ) . '</code>' ); ?> <?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_MYSQLDUMP_PATH', '/opt/local/bin/mysqldump' );</code></p>
34
+
35
+ </td>
36
+
37
+ </tr>
38
+
39
+ <tr<?php if ( defined( 'HMBKP_ZIP_PATH' ) ) { ?> class="hmbkp_active"<?php } ?>>
40
+
41
+ <td><code>HMBKP_ZIP_PATH</code></td>
42
+
43
+ <td>
44
+
45
+ <?php if ( defined( 'HMBKP_ZIP_PATH' ) ) { ?>
46
+ <p><?php printf( __( 'You\'ve set it to: %s', 'hmbkp' ), '<code>' . HMBKP_ZIP_PATH . '</code>' ); ?></p>
47
+ <?php } ?>
48
+
49
+ <p><?php printf( __( 'The path to your %1$s executable. Will be used to zip up your %2$s and %3$s if available.', 'hmbkp' ), '<code>zip</code>', '<code>' . __( 'files', 'hmbkp' ) . '</code>', '<code>' . __( 'database', 'hmbkp' ) . '</code>' ); ?> <?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_ZIP_PATH', '/opt/local/bin/zip' );</code></p>
50
+
51
+ </td>
52
+
53
+ </tr>
54
+
55
+ <tr<?php if ( defined( 'HMBKP_EXCLUDE' ) ) { ?> class="hmbkp_active"<?php } ?>>
56
+
57
+ <td><code>HMBKP_EXCLUDE</code></td>
58
+
59
+ <td>
60
+
61
+ <?php if ( defined( 'HMBKP_EXCLUDE' ) ) { ?>
62
+ <p><?php printf( __( 'You\'ve set it to: %s', 'hmbkp' ), '<code>' . HMBKP_EXCLUDE . '</code>' ); ?></p>
63
+ <?php } ?>
64
+
65
+ <p><?php _e( 'Comma separated list of files or directories to exclude, the backups directory is automatically excluded.', 'hmbkp' ); ?> <?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_EXCLUDE', '/wp-content/uploads/, /stats/, .svn/, *.txt' );</code></p>
66
+
67
+ </td>
68
+
69
+ </tr>
70
+
71
+ <tr<?php if ( defined( 'HMBKP_CAPABILITY' ) ) { ?> class="hmbkp_active"<?php } ?>>
72
+
73
+ <td><code>HMBKP_CAPABILITY</code></td>
74
+
75
+ <td>
76
+
77
+ <?php if ( defined( 'HMBKP_CAPABILITY' ) ) { ?>
78
+ <p><?php printf( __( 'You\'ve set it to: %s', 'hmbkp' ), '<code>' . HMBKP_CAPABILITY . '</code>' ); ?></p>
79
+ <?php } ?>
80
+
81
+ <p><?php printf( __( 'The capability to use when calling %1$s. Defaults to %2$s.', 'hmbkp' ), '<code>add_menu_page</code>', '<code>manage_options</code>' ); ?> <?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_CAPABILITY', 'edit_posts' );</code></p>
82
+
83
+ </td>
84
+
85
+ </tr>
86
+
87
+ <tr<?php if ( defined( 'HMBKP_ROOT' ) ) { ?> class="hmbkp_active"<?php } ?>>
88
+
89
+ <td><code>HMBKP_ROOT</code></td>
90
+
91
+ <td>
92
+
93
+ <?php if ( defined( 'HMBKP_ROOT' ) ) { ?>
94
+ <p><?php printf( __( 'You\'ve set it to: %s', 'hmbkp' ), '<code>' . HMBKP_ROOT . '</code>' ); ?></p>
95
+ <?php } ?>
96
+
97
+ <p><?php printf( __( 'The root directory that is backed up. Defaults to %s.', 'hmbkp' ), '<code>' . HM_Backup::get_home_path() . '</code>' ); ?> <?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_ROOT', ABSPATH . 'wp/' );</code></p>
98
+
99
+ </td>
100
+
101
+ </tr>
102
+
103
+ <tr<?php if ( defined( 'HMBKP_SCHEDULE_TIME' ) && HMBKP_SCHEDULE_TIME !== '11pm' ) { ?> class="hmbkp_active"<?php } ?>>
104
+
105
+ <td><code>HMBKP_SCHEDULE_TIME</code></td>
106
+
107
+ <td>
108
+
109
+ <?php if ( defined( 'HMBKP_SCHEDULE_TIME' ) && HMBKP_SCHEDULE_TIME !== '11pm' ) { ?>
110
+ <p><?php printf( __( 'You\'ve set it to: %s', 'hmbkp' ), '<code>' . HMBKP_SCHEDULE_TIME . '</code>' ); ?></p>
111
+ <?php } ?>
112
+
113
+ <p><?php printf( __( 'The time that your schedules should run. Defaults to %s.', 'hmbkp' ), '<code>23:00</code>' ); ?> <?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_SCHEDULE_TIME', '07:30' );</code></p>
114
+
115
+ </td>
116
+
117
+ </tr>
118
+
119
+ <?php foreach ( HMBKP_Services::get_services() as $file => $service )
120
+ echo wp_kses_post( call_user_func( array( $service, 'constant' ) ) ); ?>
121
+
122
+ </table>
123
 
124
  </div>
admin/page.php CHANGED
@@ -1,7 +1,5 @@
1
  <div class="wrap">
2
 
3
- <?php screen_icon( HMBKP_PLUGIN_SLUG ); ?>
4
-
5
  <h2>
6
  <?php _e( 'Manage Backups', 'hmbkp' ); ?>
7
 
@@ -11,7 +9,7 @@
11
 
12
  <?php } else { ?>
13
 
14
- <a id="intercom-info" class="colorbox add-new-h2" href="<?php echo wp_nonce_url( add_query_arg( array( 'action' => 'load_enable_support' ), is_multisite() ? admin_url( 'admin-ajax.php' ) : network_admin_url( 'admin-ajax.php' ) ), 'hmbkp_nonce' ); ?>">Enable Support</a>
15
 
16
  <?php } ?>
17
 
@@ -22,16 +20,12 @@
22
 
23
  <?php include_once( HMBKP_PLUGIN_PATH . '/admin/backups.php' ); ?>
24
 
25
- <?php else : ?>
26
-
27
- <p><strong><?php _e( 'You need to fix the issues detailed above before BackUpWordPress can start.', 'hmbkp' ); ?></strong></p>
28
-
29
- <?php endif; ?>
30
-
31
  <p class="howto"><?php printf( __( 'If you\'re finding BackUpWordPress useful, please %1$s rate it on the plugin directory. %2$s', 'hmbkp' ), '<a href="http://wordpress.org/support/view/plugin-reviews/backupwordpress">', '</a>' ); ?></p>
32
 
33
  <p class="howto"><?php _e( 'If you need help getting things working then check the FAQ by clicking on help in the top right hand corner of this page.', 'hmbkp' ); ?></p>
34
 
35
- <p class="howto"><strong><?php printf( __( 'Wish you could store your backups in a safer place? Our %1$spremium extensions%2$s enable automatic backups to Dropbox, FTP, Google Drive and more.', 'hmbkp' ), '<a href="http://bwp.hmn.md/?utm_source=wordpress-org&utm_medium=wp-admin&utm_campaign=freeplugin">', '</a>' ); ?></strong></p>
 
 
36
 
37
  </div>
1
  <div class="wrap">
2
 
 
 
3
  <h2>
4
  <?php _e( 'Manage Backups', 'hmbkp' ); ?>
5
 
9
 
10
  <?php } else { ?>
11
 
12
+ <a id="intercom-info" class="colorbox add-new-h2" href="<?php echo wp_nonce_url( add_query_arg( array( 'action' => 'load_enable_support' ), is_multisite() ? admin_url( 'admin-ajax.php' ) : network_admin_url( 'admin-ajax.php' ) ), 'hmbkp_nonce' ); ?>"><?php _e( 'Enable Support', 'hmbkp' ); ?></a>
13
 
14
  <?php } ?>
15
 
20
 
21
  <?php include_once( HMBKP_PLUGIN_PATH . '/admin/backups.php' ); ?>
22
 
 
 
 
 
 
 
23
  <p class="howto"><?php printf( __( 'If you\'re finding BackUpWordPress useful, please %1$s rate it on the plugin directory. %2$s', 'hmbkp' ), '<a href="http://wordpress.org/support/view/plugin-reviews/backupwordpress">', '</a>' ); ?></p>
24
 
25
  <p class="howto"><?php _e( 'If you need help getting things working then check the FAQ by clicking on help in the top right hand corner of this page.', 'hmbkp' ); ?></p>
26
 
27
+ <p class="howto"><strong><?php printf( __( 'Wish you could store your backups in a safer place? Our %1$spremium extensions%2$s enable automatic backups to Dropbox, FTP, Google Drive and more.', 'hmbkp' ), '<a href="https://bwp.hmn.md/?utm_source=wordpress-org&utm_medium=wp-admin&utm_campaign=freeplugin">', '</a>' ); ?></strong></p>
28
+
29
+ <?php endif; ?>
30
 
31
  </div>
admin/schedule-form.php CHANGED
@@ -6,63 +6,128 @@
6
 
7
  <legend><?php _e( 'Schedule Settings', 'hmbkp' ); ?></legend>
8
 
9
- <label>
10
 
11
- <?php _e( 'Backup', 'hmbkp' ); ?>
12
 
13
- <select name="hmbkp_schedule_type" id="hmbkp_schedule_type">
14
- <option<?php selected( $schedule->get_type(), 'complete' ); ?> value="complete"><?php _e( 'Both Database &amp; files', 'hmbkp' ); ?></option>
15
- <option<?php selected( $schedule->get_type(), 'file' ); ?> value="file"><?php _e( 'Files only', 'hmbkp' ); ?></option>
16
- <option<?php selected( $schedule->get_type(), 'database' ); ?> value="database"><?php _e( 'Database only', 'hmbkp' ); ?></option>
17
- </select>
18
 
19
- </label>
20
 
21
- <label>
22
 
23
- <?php _e( 'Schedule', 'hmbkp' ); ?>
24
 
25
- <select name="hmbkp_schedule_reoccurrence" id="hmbkp_schedule_reoccurrence">
26
 
27
- <option value="manually"><?php _e( 'Manual Only', 'hmbkp' ); ?></option>
28
 
29
- <?php foreach ( $schedule->get_cron_schedules() as $cron_schedule => $cron_details ) : ?>
30
 
31
- <option <?php selected( $schedule->get_reoccurrence(), $cron_schedule ); ?> value="<?php echo esc_attr( $cron_schedule ); ?>">
32
 
33
- <?php esc_html_e( $cron_details['display'], 'hmbkp' ); ?>
34
 
35
- </option>
36
 
37
- <?php endforeach; ?>
38
 
39
- </select>
40
 
41
- </label>
42
 
43
- <label>
44
 
45
- <?php _e( 'Number of backups to store on this server', 'hmbkp' ); ?>
46
 
47
- <input type="number" name="hmbkp_schedule_max_backups" min="1" step="1" value="<?php echo esc_attr( $schedule->get_max_backups() ); ?>" />
48
 
49
- <p class="description"><?php printf( __( 'Past this limit older backups will be deleted automatically. This schedule will store a maximum of %s of backups', 'hmbkp' ), '<code>' . size_format( $schedule->get_filesize() * $schedule->get_max_backups() ) . '</code>' ); ?></p>
50
 
51
- </label>
 
52
 
53
- <?php
54
 
55
- foreach ( HMBKP_Services::get_services( $schedule ) as $service )
56
- $service->field();
57
 
58
- ?>
59
 
60
- <p class="submit">
 
 
 
 
 
 
 
 
61
 
62
- <button type="submit" class="button-primary"><?php _e( 'Update', 'hmbkp' ); ?></button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
  </p>
65
 
66
  </fieldset>
67
 
68
- </form>
6
 
7
  <legend><?php _e( 'Schedule Settings', 'hmbkp' ); ?></legend>
8
 
9
+ <div>
10
 
11
+ <label for="hmbkp_schedule_type"><?php _e( 'Backup', 'hmbkp' ); ?></label>
12
 
13
+ <select name="hmbkp_schedule_type" id="hmbkp_schedule_type">
 
 
 
 
14
 
15
+ <option<?php selected( $schedule->get_type(), 'complete' ); ?> value="complete"><?php _e( 'Both Database &amp; files', 'hmbkp' ); ?></option>
16
 
17
+ <option<?php selected( $schedule->get_type(), 'file' ); ?> value="file"><?php _e( 'Files only', 'hmbkp' ); ?></option>
18
 
19
+ <option<?php selected( $schedule->get_type(), 'database' ); ?> value="database"><?php _e( 'Database only', 'hmbkp' ); ?></option>
20
 
21
+ </select>
22
 
23
+ </div>
24
 
25
+ <div>
26
 
27
+ <label for="hmbkp_schedule_recurrence_type"><?php _e( 'Schedule', 'hmbkp' ); ?></label>
28
 
29
+ <select name="hmbkp_schedule_recurrence[hmbkp_type]" id="hmbkp_schedule_recurrence_type">
30
 
31
+ <option value="manually"><?php _e( 'Manual Only', 'hmbkp' ); ?></option>
32
 
33
+ <?php foreach ( $schedule->get_cron_schedules() as $cron_schedule => $cron_details ) : ?>
34
 
35
+ <option <?php selected( $schedule->get_reoccurrence(), $cron_schedule ); ?> value="<?php echo esc_attr( $cron_schedule ); ?>">
36
 
37
+ <?php esc_html_e( $cron_details['display'], 'hmbkp' ); ?>
38
 
39
+ </option>
40
 
41
+ <?php endforeach; ?>
42
 
43
+ </select>
44
 
45
+ </div>
46
 
47
+ <?php if ( ! $start_time = $schedule->get_schedule_start_time() )
48
+ $start_time = time(); ?>
49
 
50
+ <div id="start-day" class="recurring-setting">
51
 
52
+ <label for="hmbkp_schedule_start_day_of_week"><?php _e( 'Start Day', 'hmbkp' ); ?></label>
 
53
 
54
+ <select id="hmbkp_schedule_start_day_of_week" name="hmbkp_schedule_recurrence[hmbkp_schedule_start_day_of_week]">
55
 
56
+ <?php $weekdays = array(
57
+ 'monday' => __( 'Monday', 'hmbkp' ),
58
+ 'tuesday' => __( 'Tuesday', 'hmbkp' ),
59
+ 'wednesday' => __( 'Wednesday', 'hmbkp' ),
60
+ 'thursday' => __( 'Thursday', 'hmbkp' ),
61
+ 'friday' => __( 'Friday', 'hmbkp' ),
62
+ 'saturday' => __( 'Saturday', 'hmbkp' ),
63
+ 'sunday' => __( 'Sunday', 'hmbkp' )
64
+ );
65
 
66
+ foreach ( $weekdays as $key => $day ) : ?>
67
+
68
+ <option value="<?php echo esc_attr( $key ) ?>" <?php selected( strtolower( date( 'l', $start_time ) ), $key ); ?>><?php echo esc_html( $day ); ?></option>
69
+
70
+ <?php endforeach; ?>
71
+
72
+ </select>
73
+
74
+ </div>
75
+
76
+ <div id="start-date" class="recurring-setting">
77
+
78
+ <label for="hmbkp_schedule_start_day_of_month"><?php _e( 'Start Day of Month', 'hmbkp' ); ?></label>
79
+
80
+ <input type="number" min="0" max="31" step="1" id="hmbkp_schedule_start_day_of_month" name="hmbkp_schedule_recurrence[hmbkp_schedule_start_day_of_month]" value="<?php echo esc_attr( date( 'j', $start_time ) ); ?>">
81
+
82
+ </div>
83
+
84
+ <div id="schedule-start" class="recurring-setting">
85
+
86
+ <label for="hmbkp_schedule_start_hours"><?php _e( 'Start time', 'hmbkp' ); ?></label>
87
+
88
+ <span class="field-group">
89
+
90
+ <label for="hmbkp_schedule_start_hours"><input type="number" min="0" max="23" step="1" name="hmbkp_schedule_recurrence[hmbkp_schedule_start_hours]" id="hmbkp_schedule_start_hours" value="<?php echo esc_attr( date( 'G', $start_time ) ); ?>">
91
+
92
+ <?php _e( 'Hours', 'hmbkp' ); ?></label>
93
+
94
+ <label for="hmbkp_schedule_start_minutes"><input type="number" min="0" max="59" step="1" name="hmbkp_schedule_recurrence[hmbkp_schedule_start_minutes]" id="hmbkp_schedule_start_minutes" value="<?php echo esc_attr( (float) date( 'i', $start_time ) ); ?>">
95
+
96
+ <?php _e( 'Minutes', 'hmbkp' ); ?></label>
97
+
98
+ </span>
99
+
100
+ <p class="twice-js description"><?php _e( 'The second backup will run 12 hours after the first', 'hmbkp' ); ?></p>
101
+
102
+ </div>
103
+
104
+ <div>
105
+
106
+ <label for="hmbkp_schedule_max_backups"><?php _e( 'Number of backups to store on this server', 'hmbkp' ); ?></label>
107
+
108
+ <input type="number" id="hmbkp_schedule_max_backups" name="hmbkp_schedule_max_backups" min="1" step="1" value="<?php echo esc_attr( $schedule->get_max_backups() ); ?>" />
109
+
110
+ <p class="description">
111
+
112
+ <?php printf( __( 'Past this limit older backups will be deleted automatically.', 'hmbkp' ) ); ?>
113
+
114
+ <?php if ( $schedule->is_filesize_cached() ) {
115
+ printf( __( 'This schedule will store a maximum of %s of backups', 'hmbkp' ), '<code>' . size_format( $schedule->get_filesize() * $schedule->get_max_backups() ) . '</code>' );
116
+ } ?>
117
+
118
+ </p>
119
+
120
+ </div>
121
+
122
+ <?php foreach ( HMBKP_Services::get_services( $schedule ) as $service )
123
+ $service->field(); ?>
124
+
125
+ <p class="submit">
126
+
127
+ <button type="submit" class="button-primary"><?php _e( 'Update', 'hmbkp' ); ?></button>
128
 
129
  </p>
130
 
131
  </fieldset>
132
 
133
+ </form>
admin/schedule.php CHANGED
@@ -15,8 +15,7 @@ $next_backup = 'title="' . esc_attr( sprintf( __( 'The next backup will be on %1
15
  switch ( $schedule->get_reoccurrence() ) :
16
 
17
  case 'hmbkp_hourly' :
18
-
19
- $reoccurrence = date_i18n( 'i', $schedule->get_next_occurrence( false ) ) === '00' ? '<span ' . $next_backup . '>' . __( 'hourly on the hour', 'hmbkp' ) . '</span>' : sprintf( __( 'hourly at %s minutes past the hour', 'hmbkp' ), '<span ' . $next_backup . '>' . str_replace( '0', '', date_i18n( 'i', $schedule->get_next_occurrence( false ) ) ) ) . '</span>';
20
 
21
  break;
22
 
15
  switch ( $schedule->get_reoccurrence() ) :
16
 
17
  case 'hmbkp_hourly' :
18
+ $reoccurrence = date_i18n( 'i', $schedule->get_next_occurrence( false ) ) === '00' ? '<span ' . $next_backup . '>' . __( 'hourly on the hour', 'hmbkp' ) . '</span>' : sprintf( __( 'hourly at %s minutes past the hour', 'hmbkp' ), '<span ' . $next_backup . '>' . intval( date_i18n( 'i', $schedule->get_next_occurrence( false ) ) ) ) . '</span>';
 
19
 
20
  break;
21
 
admin/server-info.php CHANGED
@@ -8,11 +8,31 @@
8
 
9
  <?php foreach ( HMBKP_Requirements::get_requirements( $group ) as $requirement ) : ?>
10
 
 
 
11
  <tr>
12
- <td><?php echo $requirement->name(); ?></td>
13
- <td><pre><?php echo $requirement->result(); ?></pre></td>
 
 
 
 
 
14
  </tr>
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  <?php endforeach; ?>
17
 
18
  </tbody>
8
 
9
  <?php foreach ( HMBKP_Requirements::get_requirements( $group ) as $requirement ) : ?>
10
 
11
+ <?php if ( ( is_string( $requirement->raw_result() ) && strlen( $requirement->result() ) < 20 ) || is_bool( $requirement->raw_result() ) ) { ?>
12
+
13
  <tr>
14
+
15
+ <td><?php echo esc_html( $requirement->name() ); ?></td>
16
+
17
+ <td>
18
+ <code><?php echo esc_html( $requirement->result() ); ?></code>
19
+ </td>
20
+
21
  </tr>
22
 
23
+ <?php } else { ?>
24
+
25
+ <tr>
26
+
27
+ <td colspan="2">
28
+ <?php echo esc_html( $requirement->name() ); ?>
29
+ <pre><?php echo esc_html( $requirement->result() ); ?></pre>
30
+ </td>
31
+
32
+ </tr>
33
+
34
+ <?php } ?>
35
+
36
  <?php endforeach; ?>
37
 
38
  </tbody>
assets/hmbkp.css CHANGED
@@ -1,20 +1,10 @@
1
  #icon-backupwordpress.icon32 { background: url(icon_backupwordpress_32x32.png); }
2
 
3
- tfoot p { margin: 0; font-weight: normal; }
4
- #hmbkp-constants dl { overflow: hidden; margin: 20px 0; }
5
- #hmbkp-constants dt { float: left; min-width: 250px; clear: both; padding: 6px; margin: 1px 0; cursor: pointer; }
6
- #hmbkp-constants dd { color: #666; padding: 7px 0 7px 250px; border-top: 1px solid #DFDFDF; margin: 0; cursor: pointer; min-height: 40px; }
7
- #hmbkp-constants dd:last-child { border-bottom: 1px solid #DFDFDF; }
8
- #hmbkp-constants dt:not(.hmbkp_active) + dd { background: #F9F9F9; }
9
- #hmbkp-constants dd .example { white-space: nowrap; display: none; }
10
- #hmbkp-constants dd p { margin: 0; }
11
- #hmbkp-constants dt:not(.hmbkp_active):hover + dd, #hmbkp-constants dt:not(.hmbkp_active) + dd:hover { background-color: #FFF; }
12
- #hmbkp-constants dd:hover p, #hmbkp-constants dt:hover + dd p { display: none; }
13
- #hmbkp-constants dd:hover .example, #hmbkp-constants dt:hover + dd .example { display: inline; }
14
 
15
  .completed th, .completed td { background-color: #FFFFE0; }
16
- .hmbkp_active:before { content: "\00a0 \2713 "; font-size: 11px; }
17
- .hmbkp_active, .hmbkp_active code, #hmbkp-constants .hmbkp_active + dd { background: #E5F7E8; }
18
  .contextual-help-tabs-wrap .updated { margin: 15px 0 0; }
19
 
20
  .subsubsub { width: 100%; margin: 20px 0px 0px 0px; border-bottom: 1px solid #EEE; }
@@ -24,29 +14,29 @@ tfoot p { margin: 0; font-weight: normal; }
24
  .ui-tabs-nav .ui-tabs-selected a, .ui-tabs-nav .ui-state-active a { font-weight: bold; color: #000; }
25
  .hmbkp_schedule { clear: both; overflow: hidden; }
26
 
27
-
28
  #cboxLoadedContent { margin-bottom: 0; }
29
 
 
30
  .hmbkp-form fieldset { float: left; }
31
  .js .hmbkp-form fieldset + fieldset { display: none; margin-right: -100%; }
 
32
 
33
- .hmbkp-form label { display: block; line-height: 25px; padding-bottom: 20px; border-bottom: 1px dotted #CCC; margin-bottom: 20px; width: 320px; position: relative; }
34
 
35
  .hmbkp-form legend { padding: 0 0 20px; font-size: 1.17em; font-weight: bold; }
36
- .hmbkp-form label > * { float: right; }
37
  .hmbkp-form label.hidden { display: none; }
38
- .hmbkp-form label > input[type="text"], .hmbkp-form label > select, .hmbkp-form label > input[type="password"] { min-width: 200px; }
39
- .hmbkp-form label > input[type="checkbox"] { margin-top: 6px; }
40
- .hmbkp-form label .description { line-height: 16px; margin-top: 10px; float: none; }
41
- .hmbkp-form p.submit { margin:0; padding:0; }
42
  .hmbkp-form .button-primary { float: right; }
43
  .hmbkp-form [type="number"] { min-width: 50px; width: 50px; }
44
- .hmbkp-error span { position: absolute; top: -14px; right: 1px; color: #FFF; background-color: red; white-space: nowrap; line-height: 16px; font-size: 11px; padding: 0 3px; border-radius: 3px 3px 0 0; }
45
  .hmbkp-error input[type], .hmbkp-error select { border-color: red; border-top-right-radius: 0; }
46
- .hmbkp-edit-schedule-excludes-form .code{word-break: break-word;}
47
 
48
  .hmbkp-form ul { width: 320px; overflow: hidden; }
49
- .hmbkp-form ul.hmbkp_file_list { background-color: #FFF; display: block; border-radius: 4px; box-sizing: border-box; clear: both; box-shadow: inset 0px 0px 2px #CCC; font-size: 11px; }
50
  .hmbkp_file_list li { margin: 0; padding: 5px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 16px; }
51
  .hmbkp_file_list li + li { border-top: 1px dotted #CCC; }
52
 
@@ -65,8 +55,8 @@ tfoot p { margin: 0; font-weight: normal; }
65
  .hmbkp-schedule-sentence .hmbkp-schedule-actions { visibility: visible; }
66
  .hmbkp-schedule-actions { font-size: 12px; font-weight: normal; margin: 0 0 0 26px; }
67
 
68
- .hmbkp-ajax-loading, button.hmbkp-ajax-loading { padding-left: 20px; }
69
- .hmbkp-ajax-loading:before {width: 16px;height: 16px; margin-right: 10px; content: ""; background: transparent url('spinner-2x.gif') no-repeat 0 0; background-size: 16px 16px; vertical-align: middle; display: inline-block; }
70
 
71
  button { height: 14px; }
72
 
@@ -82,11 +72,13 @@ div.hmbkp_add_exclude_rule input { min-width: 240px; float: left; line-height: 1
82
 
83
  .hmbkp-exclude-preview-open table, .hmbkp-exclude-preview-open .hmbkp-tabs, .hmbkp-exclude-preview-open p.submit { display: none; }
84
  .hmbkp-exclude-preview-open .hmbkp_add_exclude_rule { margin: 0; }
85
- .ui-tabs-panel { clear: both;}
 
86
  .ui-tabs-panel form { padding-top: 10px; }
87
 
88
- table.widefat tbody td { padding: 8px 7px; }
89
  .hmbkp-edit-schedule-excludes-form td a, .hmbkp-edit-schedule-excludes-form td span.reason { float: right; }
 
90
  .hmbkp-edit-schedule-excludes-form td span.reason { color: #CCC; }
91
  input[type="datetime-local"] { border-radius: 3px; border-width: 1px; border-style: solid; box-sizing: border-box; border-color: #DFDFDF; background-color: white; }
92
  .server-info { overflow: auto; max-height: 320px; }
1
  #icon-backupwordpress.icon32 { background: url(icon_backupwordpress_32x32.png); }
2
 
3
+ tfoot p { margin: 0; font-weight: normal; }#hmbkp-constants dl { overflow: hidden; margin: 20px 0; }
 
 
 
 
 
 
 
 
 
 
4
 
5
  .completed th, .completed td { background-color: #FFFFE0; }
6
+ .hmbkp_active td:first-child > code:before { content: "\00a0 \2713 "; font-size: 11px; }
7
+ .hmbkp_active { background: #E5F7E8; }
8
  .contextual-help-tabs-wrap .updated { margin: 15px 0 0; }
9
 
10
  .subsubsub { width: 100%; margin: 20px 0px 0px 0px; border-bottom: 1px solid #EEE; }
14
  .ui-tabs-nav .ui-tabs-selected a, .ui-tabs-nav .ui-state-active a { font-weight: bold; color: #000; }
15
  .hmbkp_schedule { clear: both; overflow: hidden; }
16
 
 
17
  #cboxLoadedContent { margin-bottom: 0; }
18
 
19
+ .hmbkp-form { overflow: hidden; }
20
  .hmbkp-form fieldset { float: left; }
21
  .js .hmbkp-form fieldset + fieldset { display: none; margin-right: -100%; }
22
+ form.hmbkp-form div.recurring-setting { display: none; }
23
 
24
+ form.hmbkp-form div { display: block; line-height: 25px; padding-bottom: 20px; border-bottom: 1px dotted #CCC; margin-bottom: 20px; width: 320px; position: relative; }
25
 
26
  .hmbkp-form legend { padding: 0 0 20px; font-size: 1.17em; font-weight: bold; }
27
+ .hmbkp-form div > select, .hmbkp-form div > input, .hmbkp-form div > span.field-group, .button-right { float: right; }
28
  .hmbkp-form label.hidden { display: none; }
29
+ .hmbkp-form div > input[type="text"], .hmbkp-form div > select, .hmbkp-form div > input[type="password"] { min-width: 200px; }
30
+ .hmbkp-form div > input[type="checkbox"] { margin-top: 6px; }
31
+ .hmbkp-form div .description { line-height: 16px; margin-top: 10px; float: none; }
32
+ .hmbkp-form p.submit { margin: 20px 0 0; padding: 0; }
33
  .hmbkp-form .button-primary { float: right; }
34
  .hmbkp-form [type="number"] { min-width: 50px; width: 50px; }
35
+ .hmbkp-error span, span.hmbkp-error { position: absolute; top: -14px; right: 1px; color: #FFF; background-color: red; white-space: nowrap; line-height: 16px; font-size: 11px; padding: 0 3px; border-radius: 3px 3px 0 0; }
36
  .hmbkp-error input[type], .hmbkp-error select { border-color: red; border-top-right-radius: 0; }
 
37
 
38
  .hmbkp-form ul { width: 320px; overflow: hidden; }
39
+ .hmbkp-form ul.hmbkp_file_list { background-color: #FFF; max-height: 200px; overflow-y: scroll; display: block; border-radius: 4px; box-sizing: border-box; clear: both; box-shadow: inset 0px 0px 2px #CCC; font-size: 11px; }
40
  .hmbkp_file_list li { margin: 0; padding: 5px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 16px; }
41
  .hmbkp_file_list li + li { border-top: 1px dotted #CCC; }
42
 
55
  .hmbkp-schedule-sentence .hmbkp-schedule-actions { visibility: visible; }
56
  .hmbkp-schedule-actions { font-size: 12px; font-weight: normal; margin: 0 0 0 26px; }
57
 
58
+ .hmbkp-ajax-loading, button.hmbkp-ajax-loading { padding-left: 20px; position: relative; }
59
+ .hmbkp-ajax-loading::before { content: ""; width: 16px; height: 16px; background-image: url('spinner-2x.gif'); background-size: 16px 16px; background-repeat: no-repeat; background-position: 0 0; position: absolute; left: -30px; top: 5px; }
60
 
61
  button { height: 14px; }
62
 
72
 
73
  .hmbkp-exclude-preview-open table, .hmbkp-exclude-preview-open .hmbkp-tabs, .hmbkp-exclude-preview-open p.submit { display: none; }
74
  .hmbkp-exclude-preview-open .hmbkp_add_exclude_rule { margin: 0; }
75
+ .hmbkp-tabs > div { display: none; }
76
+ .ui-tabs-panel { clear: both; }
77
  .ui-tabs-panel form { padding-top: 10px; }
78
 
79
+ table.widefat tbody tr:nth-child(odd) { background-color: #f9f9f9 }
80
  .hmbkp-edit-schedule-excludes-form td a, .hmbkp-edit-schedule-excludes-form td span.reason { float: right; }
81
+ .hmbkp-edit-schedule-excludes-form td span.code { float: left; width: 255px; }
82
  .hmbkp-edit-schedule-excludes-form td span.reason { color: #CCC; }
83
  input[type="datetime-local"] { border-radius: 3px; border-width: 1px; border-style: solid; box-sizing: border-box; border-color: #DFDFDF; background-color: white; }
84
  .server-info { overflow: auto; max-height: 320px; }
assets/hmbkp.js CHANGED
@@ -5,7 +5,7 @@ jQuery( document ).ready( function( $ ) {
5
 
6
  // Remove the loading class when ajax requests complete
7
  $( document ).ajaxComplete( function() {
8
- $( '.hmbkp-ajax-loading' ).removeClass( 'hmbkp-ajax-loading' );
9
  } );
10
 
11
  $( document ).on( 'click', '.hmbkp-colorbox-close', function() {
@@ -19,20 +19,14 @@ jQuery( document ).ready( function( $ ) {
19
  if ( ! $( '.subsubsub a.current' ).size() )
20
  $( '.subsubsub li:first a').addClass( 'current' );
21
 
22
- // Carries the same resize options we want
23
- // to use to all other .resize()
24
- var resize_options = {
25
- height: '85%'
26
- };
27
-
28
  // Initialize colorbox
29
  $( '.colorbox' ).colorbox( {
30
  'initialWidth' : '320px',
31
  'initialHeight' : '100px',
32
  'transition' : 'elastic',
33
- 'scrolling' : true,
34
- 'innerWidth' : "320px",
35
- 'maxHeight' : resize_options.height, //85% Takes into account the WP Admin bar.
36
  'escKey' : false,
37
  'overlayClose' : false,
38
  'onLoad' : function() {
@@ -42,15 +36,28 @@ jQuery( document ).ready( function( $ ) {
42
 
43
  $( '.hmbkp-tabs' ).tabs();
44
 
45
- if ( $( ".hmbkp-form p.submit:contains('" + hmbkp.update + "')" ).size() )
46
  $( '<button type="button" class="button-secondary hmbkp-colorbox-close">' + hmbkp.cancel + '</button>' ).appendTo( '.hmbkp-form p.submit' );
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
48
 
49
  } );
50
 
51
  // Resize the colorbox when switching tabs
52
  $( document).on( 'click', '.ui-tabs-anchor', function( e ) {
53
- $.colorbox.resize(resize_options);
54
  } );
55
 
56
  // Show delete confirm message for delete schedule
@@ -86,7 +93,7 @@ jQuery( document ).ready( function( $ ) {
86
  return;
87
  }
88
 
89
- $( this ).addClass( 'hmbkp-ajax-loading' );
90
 
91
  $.post(
92
  ajaxurl,
@@ -104,7 +111,7 @@ jQuery( document ).ready( function( $ ) {
104
 
105
  $( '.hmbkp-edit-schedule-excludes-form' ).addClass( 'hmbkp-exclude-preview-open' );
106
 
107
- $.colorbox.resize(resize_options);
108
 
109
  }
110
  )
@@ -136,12 +143,14 @@ jQuery( document ).ready( function( $ ) {
136
 
137
  $( '.hmbkp-edit-schedule-excludes-form' ).removeClass( 'hmbkp-exclude-preview-open' );
138
 
 
 
139
  } );
140
 
141
  // Add exclude rule
142
  $( document ).on( 'click', '.hmbkp_save_exclude_rule', function() {
143
 
144
- $( this ).addClass( 'hmbkp-ajax-loading' );
145
 
146
  $.post(
147
  ajaxurl,
@@ -150,7 +159,7 @@ jQuery( document ).ready( function( $ ) {
150
  $( '.hmbkp-edit-schedule-excludes-form' ).replaceWith( data );
151
  $( '.hmbkp-edit-schedule-excludes-form' ).show();
152
  $( '.hmbkp-tabs' ).tabs();
153
- $.colorbox.resize(resize_options);
154
  }
155
  );
156
 
@@ -159,9 +168,9 @@ jQuery( document ).ready( function( $ ) {
159
  // Remove exclude rule
160
  $( document ).on( 'click', '.hmbkp-edit-schedule-excludes-form td a', function( e ) {
161
 
162
- $( this ).addClass( 'hmbkp-ajax-loading' ).text( '' );
163
 
164
- $.colorbox.resize(resize_options);
165
 
166
  e.preventDefault();
167
 
@@ -172,7 +181,7 @@ jQuery( document ).ready( function( $ ) {
172
  $( '.hmbkp-edit-schedule-excludes-form' ).replaceWith( data );
173
  $( '.hmbkp-edit-schedule-excludes-form' ).show();
174
  $( '.hmbkp-tabs' ).tabs();
175
- $.colorbox.resize(resize_options);
176
  }
177
  );
178
 
@@ -183,8 +192,8 @@ jQuery( document ).ready( function( $ ) {
183
 
184
  var $isDestinationSettingsForm = $( this ).find( 'button[type="submit"]' ).hasClass( "dest-settings-save" );
185
 
186
- isNewSchedule = $( this ).closest( 'form' ).attr( 'data-schedule-action' ) == 'add' ? true : false;
187
- scheduleId = $( this ).closest( 'form' ).find( '[name="hmbkp_schedule_id"]' ).val();
188
 
189
  // Only continue if we have a schedule id
190
  if ( typeof( scheduleId ) == 'undefined' )
@@ -194,7 +203,7 @@ jQuery( document ).ready( function( $ ) {
194
  if ( ! isNewSchedule && Number( $( 'input[name="hmbkp_schedule_max_backups"]' ).val() ) < Number( $( '.hmbkp_manage_backups_row' ).size() ) && ! confirm( hmbkp.remove_old_backups ) )
195
  return false;
196
 
197
- $( this ).find( 'button[type="submit"]' ).addClass( 'hmbkp-ajax-loading' );
198
 
199
  $( '.hmbkp-error span' ).remove();
200
  $( '.hmbkp-error' ).removeClass( 'hmbkp-error' );
@@ -203,11 +212,10 @@ jQuery( document ).ready( function( $ ) {
203
 
204
  $.get(
205
  ajaxurl + '?' + $( this ).serialize(),
206
- { 'action' : 'hmnkp_edit_schedule_submit' },
207
  function( data ) {
208
 
209
- // Assume success if no data passed back
210
- if ( ( ! data || data == 0 ) && ( $isDestinationSettingsForm === false ) ) {
211
 
212
  $.colorbox.close();
213
 
@@ -218,30 +226,35 @@ jQuery( document ).ready( function( $ ) {
218
  else
219
  location.reload();
220
 
221
- } else if( ! data || data == 0 ) {
222
  // nothing for now
223
  } else {
224
 
225
  // Get the errors json string
226
- var errors = JSON.parse( data );
227
 
228
  // Loop through the errors
229
  $.each( errors, function( key, value ) {
230
 
 
 
231
  // Focus the first field that errored
232
  if ( typeof( hmbkp_focused ) == 'undefined' ) {
233
 
234
- $( '[name="' + key + '"]' ).focus();
235
 
236
  hmbkp_focused = true;
237
 
238
  }
239
 
240
  // Add an error class to all fields with errors
241
- $( '[name="' + key + '"]' ).closest( 'label' ).addClass( 'hmbkp-error' );
 
 
242
 
243
  // Add the error message
244
- $( '[name="' + key + '"]' ).after( '<span>' + value + '</span>' );
 
245
 
246
  } );
247
 
@@ -285,6 +298,7 @@ jQuery( document ).ready( function( $ ) {
285
  if ( $( '.hmbkp-schedule-sentence.hmbkp-running' ).size() )
286
  hmbkpRedirectOnBackupComplete( $( '[data-hmbkp-schedule-id]' ).attr( 'data-hmbkp-schedule-id' ), true );
287
 
 
288
  $( document ).on( 'click', '.hmbkp-run', function( e ) {
289
 
290
  $( this ).closest( '.hmbkp-schedule-sentence' ).addClass( 'hmbkp-running' );
@@ -298,12 +312,12 @@ jQuery( document ).ready( function( $ ) {
298
  { 'nonce' : hmbkp.nonce, 'action' : 'hmbkp_run_schedule', 'hmbkp_schedule_id' : scheduleId }
299
  ).done( function( data ) {
300
 
301
- catchResponseAndOfferToEmail( data );
302
 
303
  // Redirect back on error
304
  } ).fail( function( jqXHR, textStatus ) {
305
 
306
- catchResponseAndOfferToEmail( jqXHR.responseText );
307
 
308
  } );
309
 
@@ -317,13 +331,55 @@ jQuery( document ).ready( function( $ ) {
317
 
318
  } );
319
 
320
- function catchResponseAndOfferToEmail( data ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
 
322
- // Carries the same resize options we want
323
- // to use to all other .resize()
324
- var resize_options = {
325
- height: '85%'
326
- };
327
 
328
  // Backup Succeeded
329
  if ( ! data || data == 0 )
@@ -344,13 +400,13 @@ function catchResponseAndOfferToEmail( data ) {
344
 
345
  jQuery.colorbox( {
346
  'innerWidth' : "320px",
347
- 'maxHeight' : "85%",
348
  'html' : data,
349
  'overlayClose' : false,
350
  'escKey' : false,
351
  'onLoad' : function() {
352
  jQuery( '#cboxClose' ).remove();
353
- jQuery.colorbox.resize(resize_options);
354
  }
355
  } );
356
 
@@ -363,7 +419,7 @@ function catchResponseAndOfferToEmail( data ) {
363
 
364
  e.preventDefault();
365
 
366
- jQuery( this ).addClass( 'hmbkp-ajax-loading' );
367
 
368
  jQuery.post(
369
  ajaxurl,
5
 
6
  // Remove the loading class when ajax requests complete
7
  $( document ).ajaxComplete( function() {
8
+ $( '.hmbkp-ajax-loading' ).removeClass( 'hmbkp-ajax-loading' ).removeAttr( 'disabled' );
9
  } );
10
 
11
  $( document ).on( 'click', '.hmbkp-colorbox-close', function() {
19
  if ( ! $( '.subsubsub a.current' ).size() )
20
  $( '.subsubsub li:first a').addClass( 'current' );
21
 
 
 
 
 
 
 
22
  // Initialize colorbox
23
  $( '.colorbox' ).colorbox( {
24
  'initialWidth' : '320px',
25
  'initialHeight' : '100px',
26
  'transition' : 'elastic',
27
+ 'scrolling' : false,
28
+ 'innerWidth' : '320px',
29
+ 'maxHeight' : '85%', // 85% Takes into account the WP Admin bar.
30
  'escKey' : false,
31
  'overlayClose' : false,
32
  'onLoad' : function() {
36
 
37
  $( '.hmbkp-tabs' ).tabs();
38
 
39
+ if ( $( ".hmbkp-form p.submit:contains('" + hmbkp.update + "')" ).size() ) {
40
  $( '<button type="button" class="button-secondary hmbkp-colorbox-close">' + hmbkp.cancel + '</button>' ).appendTo( '.hmbkp-form p.submit' );
41
+ }
42
+
43
+
44
+ $( '.recurring-setting' ).hide();
45
+
46
+ hmbkpToggleScheduleFields( $('select#hmbkp_schedule_recurrence_type').val() );
47
+
48
+ $( document ).on( 'change', 'select#hmbkp_schedule_recurrence_type', function() {
49
+ hmbkpToggleScheduleFields( $( this ).val() );
50
+ } );
51
+
52
+ $.colorbox.resize();
53
+
54
  }
55
 
56
  } );
57
 
58
  // Resize the colorbox when switching tabs
59
  $( document).on( 'click', '.ui-tabs-anchor', function( e ) {
60
+ $.colorbox.resize();
61
  } );
62
 
63
  // Show delete confirm message for delete schedule
93
  return;
94
  }
95
 
96
+ $( this ).addClass( 'hmbkp-ajax-loading' ).attr( 'disabled', 'disabled' );
97
 
98
  $.post(
99
  ajaxurl,
111
 
112
  $( '.hmbkp-edit-schedule-excludes-form' ).addClass( 'hmbkp-exclude-preview-open' );
113
 
114
+ $.colorbox.resize();
115
 
116
  }
117
  )
143
 
144
  $( '.hmbkp-edit-schedule-excludes-form' ).removeClass( 'hmbkp-exclude-preview-open' );
145
 
146
+ $.colorbox.resize();
147
+
148
  } );
149
 
150
  // Add exclude rule
151
  $( document ).on( 'click', '.hmbkp_save_exclude_rule', function() {
152
 
153
+ $( this ).addClass( 'hmbkp-ajax-loading' ).attr( 'disabled', 'disabled' );
154
 
155
  $.post(
156
  ajaxurl,
159
  $( '.hmbkp-edit-schedule-excludes-form' ).replaceWith( data );
160
  $( '.hmbkp-edit-schedule-excludes-form' ).show();
161
  $( '.hmbkp-tabs' ).tabs();
162
+ $.colorbox.resize();
163
  }
164
  );
165
 
168
  // Remove exclude rule
169
  $( document ).on( 'click', '.hmbkp-edit-schedule-excludes-form td a', function( e ) {
170
 
171
+ $( this ).addClass( 'hmbkp-ajax-loading' ).text( '' ).attr( 'disabled', 'disabled' );
172
 
173
+ $.colorbox.resize( resize_options );
174
 
175
  e.preventDefault();
176
 
181
  $( '.hmbkp-edit-schedule-excludes-form' ).replaceWith( data );
182
  $( '.hmbkp-edit-schedule-excludes-form' ).show();
183
  $( '.hmbkp-tabs' ).tabs();
184
+ $.colorbox.resize();
185
  }
186
  );
187
 
192
 
193
  var $isDestinationSettingsForm = $( this ).find( 'button[type="submit"]' ).hasClass( "dest-settings-save" );
194
 
195
+ var isNewSchedule = $( this ).closest( 'form' ).attr( 'data-schedule-action' ) == 'add' ? true : false;
196
+ var scheduleId = $( this ).closest( 'form' ).find( '[name="hmbkp_schedule_id"]' ).val();
197
 
198
  // Only continue if we have a schedule id
199
  if ( typeof( scheduleId ) == 'undefined' )
203
  if ( ! isNewSchedule && Number( $( 'input[name="hmbkp_schedule_max_backups"]' ).val() ) < Number( $( '.hmbkp_manage_backups_row' ).size() ) && ! confirm( hmbkp.remove_old_backups ) )
204
  return false;
205
 
206
+ $( this ).find( 'button[type="submit"]' ).addClass( 'hmbkp-ajax-loading' ).attr( 'disabled', 'disabled' );
207
 
208
  $( '.hmbkp-error span' ).remove();
209
  $( '.hmbkp-error' ).removeClass( 'hmbkp-error' );
212
 
213
  $.get(
214
  ajaxurl + '?' + $( this ).serialize(),
215
+ { 'action' : 'hmbkp_edit_schedule_submit' },
216
  function( data ) {
217
 
218
+ if ( ( data.success === true ) && ( $isDestinationSettingsForm === false ) ) {
 
219
 
220
  $.colorbox.close();
221
 
226
  else
227
  location.reload();
228
 
229
+ } else if( data.success === true ) {
230
  // nothing for now
231
  } else {
232
 
233
  // Get the errors json string
234
+ var errors = data.data;
235
 
236
  // Loop through the errors
237
  $.each( errors, function( key, value ) {
238
 
239
+ var selector = key.replace(/(:|\.|\[|\])/g,'\\$1');
240
+
241
  // Focus the first field that errored
242
  if ( typeof( hmbkp_focused ) == 'undefined' ) {
243
 
244
+ $( '#' + selector ).focus();
245
 
246
  hmbkp_focused = true;
247
 
248
  }
249
 
250
  // Add an error class to all fields with errors
251
+ $( 'label[for=' + selector + ']' ).addClass( 'hmbkp-error' );
252
+
253
+ $( '#' + selector ).next( 'span' ).remove();
254
 
255
  // Add the error message
256
+ $( '#' + selector ).after( '<span class="hmbkp-error">' + value + '</span>' );
257
+
258
 
259
  } );
260
 
298
  if ( $( '.hmbkp-schedule-sentence.hmbkp-running' ).size() )
299
  hmbkpRedirectOnBackupComplete( $( '[data-hmbkp-schedule-id]' ).attr( 'data-hmbkp-schedule-id' ), true );
300
 
301
+ // Run a backup
302
  $( document ).on( 'click', '.hmbkp-run', function( e ) {
303
 
304
  $( this ).closest( '.hmbkp-schedule-sentence' ).addClass( 'hmbkp-running' );
312
  { 'nonce' : hmbkp.nonce, 'action' : 'hmbkp_run_schedule', 'hmbkp_schedule_id' : scheduleId }
313
  ).done( function( data ) {
314
 
315
+ hmbkpCatchResponseAndOfferToEmail( data );
316
 
317
  // Redirect back on error
318
  } ).fail( function( jqXHR, textStatus ) {
319
 
320
+ hmbkpCatchResponseAndOfferToEmail( jqXHR.responseText );
321
 
322
  } );
323
 
331
 
332
  } );
333
 
334
+ function hmbkpToggleScheduleFields( recurrence ){
335
+
336
+ recurrence = typeof recurrence !== 'undefined' ? recurrence : 'manually';
337
+
338
+ var settingFields = jQuery( '.recurring-setting');
339
+ var scheduleSettingFields = jQuery( '#schedule-start');
340
+ var twiceDailyNote = jQuery( 'p.twice-js' );
341
+
342
+ switch( recurrence ) {
343
+
344
+ case 'manually':
345
+ settingFields.hide();
346
+ break;
347
+
348
+ case 'hmbkp_hourly' : // fall through
349
+ case 'hmbkp_daily' :
350
+ settingFields.hide();
351
+ scheduleSettingFields.show();
352
+ twiceDailyNote.hide();
353
+ break;
354
+
355
+ case 'hmbkp_twicedaily' :
356
+ settingFields.hide();
357
+ scheduleSettingFields.show();
358
+ twiceDailyNote.show();
359
+ break;
360
+
361
+ case 'hmbkp_weekly' : // fall through
362
+ case 'hmbkp_fortnightly' :
363
+ settingFields.hide();
364
+ jQuery( '#start-day' ).show();
365
+ scheduleSettingFields.show();
366
+ twiceDailyNote.hide();
367
+ break;
368
+
369
+ case 'hmbkp_monthly' :
370
+ settingFields.hide();
371
+ scheduleSettingFields.show();
372
+ jQuery( '#start-date' ).show();
373
+ twiceDailyNote.hide();
374
+ break;
375
+
376
+ }
377
+
378
+ jQuery.colorbox.resize();
379
+
380
+ }
381
 
382
+ function hmbkpCatchResponseAndOfferToEmail( data ) {
 
 
 
 
383
 
384
  // Backup Succeeded
385
  if ( ! data || data == 0 )
400
 
401
  jQuery.colorbox( {
402
  'innerWidth' : "320px",
403
+ 'maxHeight' : "100%",
404
  'html' : data,
405
  'overlayClose' : false,
406
  'escKey' : false,
407
  'onLoad' : function() {
408
  jQuery( '#cboxClose' ).remove();
409
+ jQuery.colorbox.resize();
410
  }
411
  } );
412
 
419
 
420
  e.preventDefault();
421
 
422
+ jQuery( this ).addClass( 'hmbkp-ajax-loading' ).attr( 'disabled', 'disabled' );
423
 
424
  jQuery.post(
425
  ajaxurl,
backupwordpress.php CHANGED
@@ -5,7 +5,7 @@ Plugin Name: BackUpWordPress
5
  Plugin URI: http://hmn.md/backupwordpress/
6
  Description: Simple automated backups of your WordPress powered website. Once activated you'll find me under <strong>Tools &rarr; Backups</strong>.
7
  Author: Human Made Limited
8
- Version: 2.5
9
  Author URI: http://hmn.md/
10
  */
11
 
@@ -62,9 +62,6 @@ if ( ! defined( 'HMBKP_REQUIRED_WP_VERSION' ) )
62
  if ( ! defined( 'WP_MAX_MEMORY_LIMIT' ) )
63
  define( 'WP_MAX_MEMORY_LIMIT', '256M' );
64
 
65
- if ( ! defined( 'HMBKP_SCHEDULE_TIME' ) )
66
- define( 'HMBKP_SCHEDULE_TIME', '11pm' );
67
-
68
  if ( ! defined( 'HMBKP_ADMIN_PAGE' ) ) {
69
 
70
  if ( is_multisite() )
5
  Plugin URI: http://hmn.md/backupwordpress/
6
  Description: Simple automated backups of your WordPress powered website. Once activated you'll find me under <strong>Tools &rarr; Backups</strong>.
7
  Author: Human Made Limited
8
+ Version: 2.6
9
  Author URI: http://hmn.md/
10
  */
11
 
62
  if ( ! defined( 'WP_MAX_MEMORY_LIMIT' ) )
63
  define( 'WP_MAX_MEMORY_LIMIT', '256M' );
64
 
 
 
 
65
  if ( ! defined( 'HMBKP_ADMIN_PAGE' ) ) {
66
 
67
  if ( is_multisite() )
classes/class-email.php CHANGED
@@ -26,15 +26,15 @@ class HMBKP_Email_Service extends HMBKP_Service {
26
  */
27
  public function field() { ?>
28
 
29
- <label>
30
 
31
- <?php _e( 'Email notification', 'hmbkp' ); ?>
32
 
33
- <input type="email" name="<?php echo esc_attr( $this->get_field_name( 'email' ) ); ?>" value="<?php echo esc_attr( $this->get_field_value( 'email' ) ); ?>" />
34
 
35
- <p class="description"><?php printf( __( 'Receive a notification email when a backup completes, if the backup is small enough (&lt; %s) then it will be attached to the email. Separate multiple email address\'s with a comma.', 'hmbkp' ), '<code>' . size_format( hmbkp_get_max_attachment_size() ) . '</code>' ); ?></p>
36
 
37
- </label>
38
 
39
  <?php }
40
 
@@ -50,8 +50,21 @@ class HMBKP_Email_Service extends HMBKP_Service {
50
 
51
  public static function constant() { ?>
52
 
53
- <dt<?php if ( defined( 'HMBKP_ATTACHMENT_MAX_FILESIZE' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_ATTACHMENT_MAX_FILESIZE</code></dt>
54
- <dd><p><?php printf( __( 'The maximum filesize of your backup that will be attached to your notification emails . Defaults to %s.', 'hmbkp' ), '<code>10MB</code>' ); ?><p class="example"><?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_ATTACHMENT_MAX_FILESIZE', '25MB' );</code></p></dd>
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
  <?php }
57
 
@@ -73,7 +86,7 @@ class HMBKP_Email_Service extends HMBKP_Service {
73
  return '';
74
 
75
  }
76
-
77
  /**
78
  * Used to determine if the service is in use or not
79
  */
@@ -94,17 +107,27 @@ class HMBKP_Email_Service extends HMBKP_Service {
94
 
95
  if ( isset( $new_data['email'] ) ) {
96
 
97
- if ( ! empty( $new_data['email'] ) )
98
- foreach ( explode( ',', $new_data['email'] ) as $email )
99
- if ( ! is_email( $email ) )
 
 
 
 
100
  $errors['email'] = sprintf( __( '%s isn\'t a valid email', 'hmbkp' ), $email );
 
101
 
102
- if ( ! empty( $errors['email'] ) )
103
- $new_data['email'] = '';
 
104
 
105
- }
106
 
107
- return $errors;
 
 
 
 
108
 
109
  }
110
 
@@ -192,4 +215,4 @@ class HMBKP_Email_Service extends HMBKP_Service {
192
  }
193
 
194
  // Register the service
195
- HMBKP_Services::register( __FILE__, 'HMBKP_Email_Service' );
26
  */
27
  public function field() { ?>
28
 
29
+ <div>
30
 
31
+ <label for="<?php echo esc_attr( $this->get_field_name( 'email' ) ); ?>"><?php _e( 'Email notification', 'hmbkp' ); ?></label>
32
 
33
+ <input type="email" id="<?php echo esc_attr( $this->get_field_name( 'email' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'email' ) ); ?>" value="<?php echo esc_attr( $this->get_field_value( 'email' ) ); ?>" />
34
 
35
+ <p class="description"><?php printf( __( 'Receive a notification email when a backup completes, if the backup is small enough (&lt; %s) then it will be attached to the email. Separate multiple email address\'s with a comma.', 'hmbkp' ), '<code>' . size_format( hmbkp_get_max_attachment_size() ) . '</code>' ); ?></p>
36
 
37
+ </div>
38
 
39
  <?php }
40
 
50
 
51
  public static function constant() { ?>
52
 
53
+ <tr<?php if ( defined( 'HMBKP_ATTACHMENT_MAX_FILESIZE' ) ) { ?> class="hmbkp_active"<?php } ?>>
54
+
55
+ <td><code>HMBKP_ATTACHMENT_MAX_FILESIZE</code></td>
56
+
57
+ <td>
58
+
59
+ <?php if ( defined( 'HMBKP_ATTACHMENT_MAX_FILESIZE' ) ) { ?>
60
+ <p><?php printf( __( 'You\'ve set it to: %s', 'hmbkp' ), '<code>' . HMBKP_ATTACHMENT_MAX_FILESIZE . '</code>' ); ?></p>
61
+ <?php } ?>
62
+
63
+ <p><?php printf( __( 'The maximum filesize of your backup that will be attached to your notification emails . Defaults to %s.', 'hmbkp' ), '<code>10MB</code>' ); ?> <?php _e( 'e.g.', 'hmbkp' ); ?> <code>define( 'HMBKP_ATTACHMENT_MAX_FILESIZE', '25MB' );</code></p>
64
+
65
+ </td>
66
+
67
+ </tr>
68
 
69
  <?php }
70
 
86
  return '';
87
 
88
  }
89
+
90
  /**
91
  * Used to determine if the service is in use or not
92
  */
107
 
108
  if ( isset( $new_data['email'] ) ) {
109
 
110
+ if ( ! empty( $new_data['email'] ) ) {
111
+
112
+ foreach ( explode( ',', $new_data['email'] ) as $email ) {
113
+
114
+ $email = trim( $email );
115
+
116
+ if ( ! is_email( $email ) ) {
117
  $errors['email'] = sprintf( __( '%s isn\'t a valid email', 'hmbkp' ), $email );
118
+ }
119
 
120
+ if ( ! empty( $errors['email'] ) ) {
121
+ $new_data['email'] = '';
122
+ }
123
 
124
+ }
125
 
126
+ }
127
+
128
+ return $errors;
129
+
130
+ }
131
 
132
  }
133
 
215
  }
216
 
217
  // Register the service
218
+ HMBKP_Services::register( __FILE__, 'HMBKP_Email_Service' );
classes/class-requirements.php CHANGED
@@ -563,6 +563,8 @@ class HMBKP_Requirement_Calculated_Size extends HMBKP_Requirement {
563
  */
564
  protected function test() {
565
 
 
 
566
  $schedules = HMBKP_Schedules::get_instance();
567
 
568
  foreach ( $schedules->get_schedules() as $schedule )
563
  */
564
  protected function test() {
565
 
566
+ $backup_sizes = array();
567
+
568
  $schedules = HMBKP_Schedules::get_instance();
569
 
570
  foreach ( $schedules->get_schedules() as $schedule )
classes/class-schedule.php CHANGED
@@ -31,16 +31,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
31
  */
32
  private $options = array();
33
 
34
- /**
35
- * The schedule start time
36
- *
37
- * (default value: current_time( 'timestamp' ))
38
- *
39
- * @var mixed
40
- * @access private
41
- */
42
- private $schedule_start_time = 0;
43
-
44
  /**
45
  * Setup the schedule object
46
  * Loads the options from the database and populates properties
@@ -85,18 +75,20 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
85
  if ( defined( 'HMBKP_ZIP_PATH' ) && HMBKP_ZIP_PATH === 'PclZip' && $this->skip_zip_archive = true )
86
  $this->set_zip_command_path( false );
87
 
 
 
 
88
  // Set the path - TODO remove external function dependancy
89
  $this->set_path( hmbkp_path() );
90
 
91
- $hmbkp_schedules = $this->get_cron_schedules();
92
-
93
  // Set the archive filename to site name + schedule slug + date
94
  $this->set_archive_filename( implode( '-', array( sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ), $this->get_id(), $this->get_type(), date( 'Y-m-d-H-i-s', current_time( 'timestamp' ) ) ) ) . '.zip' );
95
  $this->set_database_dump_filename( implode( '-', array( sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ), $this->get_id(), $this->get_type(), date( 'Y-m-d-H-i-s', current_time( 'timestamp' ) ) ) ) . '.sql' );
96
 
97
  // Setup the schedule if it isn't set
98
- if ( ( ! $this->get_next_occurrence() && in_array( $this->get_reoccurrence(), array_keys( $hmbkp_schedules ) ) ) || ( date( get_option( 'time_format' ), strtotime( HMBKP_SCHEDULE_TIME ) - ( get_option( 'gmt_offset' ) * 3600 ) ) !== date( get_option( 'time_format' ), $this->get_next_occurrence() ) ) )
99
  $this->schedule();
 
100
 
101
  }
102
 
@@ -132,9 +124,9 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
132
  */
133
  public function get_name() {
134
 
135
- $reoccurence = ( 'manually' === $this->get_reoccurrence() ) ? $this->get_reoccurrence() : substr( $this->get_reoccurrence(), 6 );
136
 
137
- return ucwords( $this->get_type() ) . ' ' . $reoccurence;
138
 
139
  }
140
 
@@ -234,7 +226,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
234
  public function set_max_backups( $max ) {
235
 
236
  if ( empty( $max ) || ! is_int( $max ) )
237
- return new WP_Error( 'hmbkp_invalid_type_error', sprintf( __( 'Argument 1 for %s must be a valid integer', 'hmbkp' ) ), __METHOD__ );
238
 
239
  $this->options['max_backups'] = $max;
240
 
@@ -426,37 +418,31 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
426
  if ( $this->get_reoccurrence() === 'manually' )
427
  return 0;
428
 
429
- if ( empty( $this->schedule_start_time ) ) {
 
430
 
431
- if ( defined( 'HMBKP_SCHEDULE_TIME' ) && HMBKP_SCHEDULE_TIME )
432
- $date = strtotime( HMBKP_SCHEDULE_TIME );
433
 
434
- else
435
- $date = strtotime( '11pm' );
436
-
437
- // Convert to UTC
438
- $date -= get_option( 'gmt_offset' ) * 3600;
439
-
440
- // if the scheduled time already passed today then start at the next interval instead
441
- if ( $date <= strtotime( 'now' ) )
442
- $date += $this->get_interval();
443
-
444
- $this->set_schedule_start_time( $date );
445
- }
446
-
447
- return $this->schedule_start_time;
448
 
449
  }
450
 
451
  /**
452
  * Set the schedule start time.
453
  *
454
- * @access public
455
- * @param int $timestamp in UTC
456
- * @return void
457
  */
458
- public function set_schedule_start_time( $timestamp ) {
459
- $this->schedule_start_time = $timestamp;
 
 
 
 
 
 
 
 
 
460
  }
461
 
462
  /**
@@ -467,8 +453,9 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
467
  public function get_reoccurrence() {
468
 
469
  // Default to no reoccurrence
470
- if ( empty( $this->options['reoccurrence'] ) )
471
  $this->set_reoccurrence( 'manually' );
 
472
 
473
  return $this->options['reoccurrence'];
474
 
@@ -486,20 +473,24 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
486
 
487
  // Check it's valid
488
  if ( ! is_string( $reoccurrence ) || ! trim( $reoccurrence ) || ( ! in_array( $reoccurrence, array_keys( $hmbkp_schedules ) ) ) && $reoccurrence !== 'manually' )
489
- return new WP_Error( 'hmbkp_invalid_argument_error', sprintf( __( 'Argument 1 for %s must be a valid cron reoccurrence or "manually"', 'hmbkp' ) ), __METHOD__ );
490
 
491
- if ( isset( $this->options['reoccurrence'] ) && $this->options['reoccurrence'] === $reoccurrence )
 
492
  return;
493
 
494
  $this->options['reoccurrence'] = $reoccurrence;
495
 
496
- if ( $reoccurrence === 'manually' )
497
  $this->unschedule();
 
498
 
499
- else
500
  $this->schedule();
 
501
 
502
  return true;
 
503
  }
504
 
505
  /**
@@ -524,7 +515,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
524
  *
525
  * @return array
526
  */
527
- public function get_cron_schedules() {
528
 
529
  $schedules = wp_get_schedules();
530
 
@@ -556,14 +547,18 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
556
 
557
  }
558
 
 
 
 
 
559
 
560
  /**
561
  * Get the path to the backup running file that stores the running backup status
562
  *
563
- * @access private
564
  * @return string
565
  */
566
- private function get_schedule_running_path() {
567
  return $this->get_path() . '/.schedule-' . $this->get_id() . '-running';
568
  }
569
 
@@ -577,7 +572,9 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
577
  // Clear any existing hooks
578
  $this->unschedule();
579
 
580
- wp_schedule_event( $this->get_schedule_start_time(), $this->get_reoccurrence(), 'hmbkp_schedule_hook', array( 'id' => $this->get_id() ) );
 
 
581
 
582
  }
583
 
@@ -621,36 +618,43 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
621
  }
622
 
623
  /**
624
- * Get the status of the running backup.
625
  *
626
  * @access public
627
  * @return string
628
  */
629
- public function get_status() {
630
 
631
  if ( ! file_exists( $this->get_schedule_running_path() ) )
632
  return '';
633
 
634
- $status = explode( '::', file_get_contents( $this->get_schedule_running_path() ) );
635
 
636
- return end( $status );
 
 
 
637
 
638
  }
639
 
640
  /**
641
- * Get the filename that the running status is stored in.
642
  *
643
  * @access public
644
  * @return string
645
  */
646
- public function get_running_backup_filename() {
647
 
648
  if ( ! file_exists( $this->get_schedule_running_path() ) )
649
  return '';
650
 
651
- $backup_running_file = explode( '::', file_get_contents( $this->get_schedule_running_path() ) );
 
 
 
 
 
652
 
653
- return reset( $backup_running_file );
654
  }
655
 
656
  /**
@@ -665,18 +669,52 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
665
  if ( ! $handle = fopen( $this->get_schedule_running_path(), 'w' ) )
666
  return;
667
 
668
- fwrite( $handle, $this->get_archive_filename() . '::' . $message );
 
 
 
 
 
 
669
 
670
  fclose( $handle );
671
 
672
  }
673
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
674
  /**
675
  * Hook into the actions fired in HM Backup and set the status
676
  * @param $action
677
  */
678
  protected function do_action( $action ) {
679
 
 
 
 
 
 
 
 
 
680
  switch ( $action ) :
681
 
682
  case 'hmbkp_mysqldump_started' :
@@ -746,14 +784,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
746
 
747
  endswitch;
748
 
749
- // Pass the actions to all the services
750
- foreach ( HMBKP_Services::get_services( $this ) as $service ) {
751
- $service->action( $action );
752
- }
753
-
754
- // Fire the parent function as well
755
- parent::do_action( $action );
756
-
757
  }
758
 
759
  /**
@@ -806,19 +836,20 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
806
 
807
  // Check that it's a valid filepath
808
  if ( empty( $filepath ) || ! is_string( $filepath ) )
809
- return new WP_Error( 'hmbkp_empty_string_error', sprintf( __( 'Argument 1 for %s must be a non empty string', 'hmbkp' ) ), __METHOD__ );
810
 
811
  // Make sure it exists
812
  if ( ! file_exists( $filepath ) )
813
- return new WP_Error( 'hmbkp_file_error', sprintf( __( '%s dpesn\'t exist', 'hmbkp' ) ), $filepath );
814
 
815
  // Make sure it was created by this schedule
816
  if ( strpos( $filepath, $this->get_id() ) === false )
817
- return new WP_Error( 'hmbkp_backup_error', sprintf( __( 'That backup wasn\'t created by this schedule', 'hmbkp' ) ) );
818
 
819
  unlink( $filepath );
820
 
821
  return true;
 
822
  }
823
 
824
  /**
31
  */
32
  private $options = array();
33
 
 
 
 
 
 
 
 
 
 
 
34
  /**
35
  * Setup the schedule object
36
  * Loads the options from the database and populates properties
75
  if ( defined( 'HMBKP_ZIP_PATH' ) && HMBKP_ZIP_PATH === 'PclZip' && $this->skip_zip_archive = true )
76
  $this->set_zip_command_path( false );
77
 
78
+ if ( defined( 'HMBKP_SCHEDULE_START_TIME' ) && strtotime( 'HMBKP_SCHEDULE_START_TIME' ) )
79
+ $this->set_schedule_start_time( strtotime( 'HMBKP_SCHEDULE_START_TIME' ) );
80
+
81
  // Set the path - TODO remove external function dependancy
82
  $this->set_path( hmbkp_path() );
83
 
 
 
84
  // Set the archive filename to site name + schedule slug + date
85
  $this->set_archive_filename( implode( '-', array( sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ), $this->get_id(), $this->get_type(), date( 'Y-m-d-H-i-s', current_time( 'timestamp' ) ) ) ) . '.zip' );
86
  $this->set_database_dump_filename( implode( '-', array( sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ), $this->get_id(), $this->get_type(), date( 'Y-m-d-H-i-s', current_time( 'timestamp' ) ) ) ) . '.sql' );
87
 
88
  // Setup the schedule if it isn't set
89
+ if ( ( ! $this->is_cron_scheduled() && $this->get_reoccurrence() !== 'manually' ) ) {
90
  $this->schedule();
91
+ }
92
 
93
  }
94
 
124
  */
125
  public function get_name() {
126
 
127
+ $recurrence = ( 'manually' === $this->get_reoccurrence() ) ? $this->get_reoccurrence() : substr( $this->get_reoccurrence(), 6 );
128
 
129
+ return ucwords( $this->get_type() ) . ' ' . $recurrence;
130
 
131
  }
132
 
226
  public function set_max_backups( $max ) {
227
 
228
  if ( empty( $max ) || ! is_int( $max ) )
229
+ return new WP_Error( 'hmbkp_invalid_type_error', sprintf( __( 'Argument 1 for %s must be a valid integer', 'hmbkp' ), __METHOD__ ) );
230
 
231
  $this->options['max_backups'] = $max;
232
 
418
  if ( $this->get_reoccurrence() === 'manually' )
419
  return 0;
420
 
421
+ if ( ! empty( $this->options['schedule_start_time'] ) )
422
+ return $this->options['schedule_start_time'];
423
 
424
+ $this->set_schedule_start_time( time() );
 
425
 
426
+ return time();
 
 
 
 
 
 
 
 
 
 
 
 
 
427
 
428
  }
429
 
430
  /**
431
  * Set the schedule start time.
432
  *
433
+ * @param array $args
 
 
434
  */
435
+ public function set_schedule_start_time( $time ) {
436
+
437
+ // Don't allow setting the start time in the past
438
+ if ( (int) $time <= time() ) {
439
+ return new WP_Error( 'hmbkp_invalid_argument_error', sprintf( __( 'Argument 1 for %s must be a valid future timestamp', 'hmbkp' ), __METHOD__ ) );
440
+ }
441
+
442
+ $this->options['schedule_start_time'] = $time;
443
+
444
+ $this->schedule();
445
+
446
  }
447
 
448
  /**
453
  public function get_reoccurrence() {
454
 
455
  // Default to no reoccurrence
456
+ if ( empty( $this->options['reoccurrence'] ) ) {
457
  $this->set_reoccurrence( 'manually' );
458
+ }
459
 
460
  return $this->options['reoccurrence'];
461
 
473
 
474
  // Check it's valid
475
  if ( ! is_string( $reoccurrence ) || ! trim( $reoccurrence ) || ( ! in_array( $reoccurrence, array_keys( $hmbkp_schedules ) ) ) && $reoccurrence !== 'manually' )
476
+ return new WP_Error( 'hmbkp_invalid_argument_error', sprintf( __( 'Argument 1 for %s must be a valid cron reoccurrence or "manually"', 'hmbkp' ), __METHOD__ ) );
477
 
478
+ // If the recurrence is already set to the same thing then there's no need to continue
479
+ if ( isset( $this->options['reoccurrence'] ) && $this->options['reoccurrence'] === $reoccurrence && $this->is_cron_scheduled() )
480
  return;
481
 
482
  $this->options['reoccurrence'] = $reoccurrence;
483
 
484
+ if ( $reoccurrence === 'manually' ) {
485
  $this->unschedule();
486
+ }
487
 
488
+ else {
489
  $this->schedule();
490
+ }
491
 
492
  return true;
493
+
494
  }
495
 
496
  /**
515
  *
516
  * @return array
517
  */
518
+ public static function get_cron_schedules() {
519
 
520
  $schedules = wp_get_schedules();
521
 
547
 
548
  }
549
 
550
+ public function is_cron_scheduled() {
551
+ return (bool) $this->get_next_occurrence();
552
+ }
553
+
554
 
555
  /**
556
  * Get the path to the backup running file that stores the running backup status
557
  *
558
+ * @access public
559
  * @return string
560
  */
561
+ public function get_schedule_running_path() {
562
  return $this->get_path() . '/.schedule-' . $this->get_id() . '-running';
563
  }
564
 
572
  // Clear any existing hooks
573
  $this->unschedule();
574
 
575
+ $schedule_timestamp = $this->get_schedule_start_time();
576
+
577
+ wp_schedule_event( $schedule_timestamp, $this->get_reoccurrence(), 'hmbkp_schedule_hook', array( 'id' => $this->get_id() ) );
578
 
579
  }
580
 
618
  }
619
 
620
  /**
621
+ * Get the filename that the running status is stored in.
622
  *
623
  * @access public
624
  * @return string
625
  */
626
+ public function get_running_backup_filename() {
627
 
628
  if ( ! file_exists( $this->get_schedule_running_path() ) )
629
  return '';
630
 
631
+ $status = json_decode( file_get_contents( $this->get_schedule_running_path() ) );
632
 
633
+ if ( ! empty( $status->filename ) )
634
+ return $status->filename;
635
+
636
+ return '';
637
 
638
  }
639
 
640
  /**
641
+ * Get the status of the running backup.
642
  *
643
  * @access public
644
  * @return string
645
  */
646
+ public function get_status() {
647
 
648
  if ( ! file_exists( $this->get_schedule_running_path() ) )
649
  return '';
650
 
651
+ $status = json_decode( file_get_contents( $this->get_schedule_running_path() ) );
652
+
653
+ if ( ! empty( $status->status ) )
654
+ return $status->status;
655
+
656
+ return '';
657
 
 
658
  }
659
 
660
  /**
669
  if ( ! $handle = fopen( $this->get_schedule_running_path(), 'w' ) )
670
  return;
671
 
672
+ $status = json_encode( (object) array(
673
+ 'filename' => $this->get_archive_filename(),
674
+ 'started' => $this->get_schedule_running_start_time(),
675
+ 'status' => $message
676
+ ) );
677
+
678
+ fwrite( $handle, $status );
679
 
680
  fclose( $handle );
681
 
682
  }
683
 
684
+ /**
685
+ * Set the time that the current running backup was started
686
+ *
687
+ * @access public
688
+ * @return int $timestamp
689
+ */
690
+ public function get_schedule_running_start_time() {
691
+
692
+ if ( ! file_exists( $this->get_schedule_running_path() ) )
693
+ return 0;
694
+
695
+ $status = json_decode( file_get_contents( $this->get_schedule_running_path() ) );
696
+
697
+ if ( ! empty( $status->started ) && (int) (string) $status->started === $status->started )
698
+ return $status->started;
699
+
700
+ return time();
701
+
702
+ }
703
+
704
  /**
705
  * Hook into the actions fired in HM Backup and set the status
706
  * @param $action
707
  */
708
  protected function do_action( $action ) {
709
 
710
+ // Pass the actions to all the services
711
+ foreach ( HMBKP_Services::get_services( $this ) as $service ) {
712
+ $service->action( $action );
713
+ }
714
+
715
+ // Fire the parent function as well
716
+ parent::do_action( $action );
717
+
718
  switch ( $action ) :
719
 
720
  case 'hmbkp_mysqldump_started' :
784
 
785
  endswitch;
786
 
 
 
 
 
 
 
 
 
787
  }
788
 
789
  /**
836
 
837
  // Check that it's a valid filepath
838
  if ( empty( $filepath ) || ! is_string( $filepath ) )
839
+ return new WP_Error( 'hmbkp_empty_string_error', sprintf( __( 'Argument 1 for %s must be a non empty string', 'hmbkp' ), __METHOD__ ) );
840
 
841
  // Make sure it exists
842
  if ( ! file_exists( $filepath ) )
843
+ return new WP_Error( 'hmbkp_file_error', sprintf( __( '%s doesn\'t exist', 'hmbkp' ), $filepath ) );
844
 
845
  // Make sure it was created by this schedule
846
  if ( strpos( $filepath, $this->get_id() ) === false )
847
+ return new WP_Error( 'hmbkp_backup_error', __( 'That backup wasn\'t created by this schedule', 'hmbkp' ) );
848
 
849
  unlink( $filepath );
850
 
851
  return true;
852
+
853
  }
854
 
855
  /**
classes/class-schedules.php CHANGED
@@ -29,6 +29,10 @@ class HMBKP_Schedules {
29
  * @access public
30
  */
31
  private function __construct() {
 
 
 
 
32
 
33
  global $wpdb;
34
 
29
  * @access public
30
  */
31
  private function __construct() {
32
+ $this->refresh_schedules();
33
+ }
34
+
35
+ public function refresh_schedules() {
36
 
37
  global $wpdb;
38
 
classes/wp-cli.php CHANGED
@@ -9,7 +9,34 @@
9
  */
10
  class BackUpCommand extends WP_CLI_Command {
11
 
12
- public function __construct( $args, $assoc_args ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  // Make sure it's possible to do a backup
15
  if ( HM_Backup::is_safe_mode_active() )
@@ -72,22 +99,5 @@ class BackUpCommand extends WP_CLI_Command {
72
 
73
  }
74
 
75
- static function help() {
76
-
77
- WP_CLI::line( <<<EOB
78
- usage: wp backup [--files_only] [--database_only] [--path<dir>] [--root<dir>] [--zip_command_path=<path>] [--mysqldump_command_path=<path>]
79
-
80
- --files_only Backup files only, default to off
81
- --database_only Backup database only, defaults to off
82
- --path dir that the backup should be save in, defaults to wp-content/backups/
83
- --root dir that should be backed up, defaults to site root.
84
- --zip_command_path path to your zip binary, standard locations are automatically used
85
- --mysqldump_command_path path to your mysqldump binary, standard locations are automatically used
86
-
87
- EOB
88
- );
89
-
90
- }
91
-
92
  }
93
- WP_CLI::add_command( 'backup', 'BackUpCommand' );
9
  */
10
  class BackUpCommand extends WP_CLI_Command {
11
 
12
+ /**
13
+ * Generate some posts.
14
+ *
15
+ * ## OPTIONS
16
+ *
17
+ * [--files_only]
18
+ * : Backup files only, default to off
19
+ *
20
+ * [--database_only]
21
+ * : Backup database only, defaults to off
22
+ *
23
+ * [--path]
24
+ * : dir that the backup should be save in, defaults to wp-content/backups/
25
+ *
26
+ * [--root]
27
+ * : dir that should be backed up, defaults to site root.
28
+ *
29
+ * [--zip_command_path]
30
+ * : path to your zip binary, standard locations are automatically used
31
+ *
32
+ * [--mysqldump_command_path]
33
+ * : path to your mysqldump binary, standard locations are automatically used
34
+ *
35
+ * ## Usage
36
+ *
37
+ * wp backupwordpress backup [--files_only] [--database_only] [--path<dir>] [--root<dir>] [--zip_command_path=<path>] [--mysqldump_command_path=<path>]
38
+ */
39
+ public function backup( $args, $assoc_args ) {
40
 
41
  // Make sure it's possible to do a backup
42
  if ( HM_Backup::is_safe_mode_active() )
99
 
100
  }
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  }
103
+ WP_CLI::add_command( 'backupwordpress', 'BackUpCommand' );
functions/core.php CHANGED
@@ -211,6 +211,7 @@ function hmbkp_setup_default_schedules() {
211
  */
212
  $database_daily = new HMBKP_Scheduled_Backup( 'default-1' );
213
  $database_daily->set_type( 'database' );
 
214
  $database_daily->set_reoccurrence( 'hmbkp_daily' );
215
  $database_daily->set_max_backups( 14 );
216
  $database_daily->save();
@@ -221,10 +222,13 @@ function hmbkp_setup_default_schedules() {
221
  */
222
  $complete_weekly = new HMBKP_Scheduled_Backup( 'default-2' );
223
  $complete_weekly->set_type( 'complete' );
 
224
  $complete_weekly->set_reoccurrence( 'hmbkp_weekly' );
225
  $complete_weekly->set_max_backups( 12 );
226
  $complete_weekly->save();
227
 
 
 
228
  function hmbkp_default_schedules_setup_warning() {
229
  echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has setup your default schedules.', 'hmbkp' ) . '</strong> ' . __( 'By default BackUpWordPress performs a daily backup of your database and a weekly backup of your database &amp; files. You can modify these schedules.', 'hmbkp' ) . '</p></div>';
230
  }
@@ -271,7 +275,7 @@ function hmbkp_rmdirtree( $dir ) {
271
  if ( is_file( $dir ) )
272
  @unlink( $dir );
273
 
274
- if ( ! is_dir( $dir ) )
275
  return false;
276
 
277
  $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
@@ -445,6 +449,11 @@ function hmbkp_possible() {
445
  if ( ! wp_is_writable( hmbkp_path() ) || ! is_dir( hmbkp_path() ) )
446
  return false;
447
 
 
 
 
 
 
448
  return true;
449
  }
450
 
@@ -466,7 +475,7 @@ function hmbkp_cleanup() {
466
  if ( $handle = opendir( $hmbkp_path ) ) {
467
 
468
  while ( false !== ( $file = readdir( $handle ) ) ) {
469
- if ( ! in_array( $file, array( '.', '..', 'index.html' ) ) && pathinfo( $file, PATHINFO_EXTENSION ) !== 'zip' )
470
  hmbkp_rmdirtree( trailingslashit( $hmbkp_path ) . $file );
471
  }
472
 
@@ -524,3 +533,126 @@ function hmbkp_is_path_accessible( $dir ) {
524
 
525
  return true;
526
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  */
212
  $database_daily = new HMBKP_Scheduled_Backup( 'default-1' );
213
  $database_daily->set_type( 'database' );
214
+ $database_daily->set_schedule_start_time( hmbkp_determine_start_time( 'hmbkp_daily', array( 'hours' => '23', 'minutes' => '0' ) ) );
215
  $database_daily->set_reoccurrence( 'hmbkp_daily' );
216
  $database_daily->set_max_backups( 14 );
217
  $database_daily->save();
222
  */
223
  $complete_weekly = new HMBKP_Scheduled_Backup( 'default-2' );
224
  $complete_weekly->set_type( 'complete' );
225
+ $complete_weekly->set_schedule_start_time( hmbkp_determine_start_time( 'hmbkp_weekly', array( 'day_of_week' => 'sunday', 'hours' => '3', 'minutes' => '0' ) ) );
226
  $complete_weekly->set_reoccurrence( 'hmbkp_weekly' );
227
  $complete_weekly->set_max_backups( 12 );
228
  $complete_weekly->save();
229
 
230
+ $schedules->refresh_schedules();
231
+
232
  function hmbkp_default_schedules_setup_warning() {
233
  echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has setup your default schedules.', 'hmbkp' ) . '</strong> ' . __( 'By default BackUpWordPress performs a daily backup of your database and a weekly backup of your database &amp; files. You can modify these schedules.', 'hmbkp' ) . '</p></div>';
234
  }
275
  if ( is_file( $dir ) )
276
  @unlink( $dir );
277
 
278
+ if ( ! is_dir( $dir ) || ! is_readable( $dir ) )
279
  return false;
280
 
281
  $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
449
  if ( ! wp_is_writable( hmbkp_path() ) || ! is_dir( hmbkp_path() ) )
450
  return false;
451
 
452
+ $test_backup = new HMBKP_Scheduled_Backup( 'test_backup' );
453
+
454
+ if ( ! is_readable( $test_backup->get_root() ) )
455
+ return false;
456
+
457
  return true;
458
  }
459
 
475
  if ( $handle = opendir( $hmbkp_path ) ) {
476
 
477
  while ( false !== ( $file = readdir( $handle ) ) ) {
478
+ if ( ! in_array( $file, array( '.', '..', 'index.html' ) ) && pathinfo( $file, PATHINFO_EXTENSION ) !== 'zip' && strpos( $file, '-running' ) === false )
479
  hmbkp_rmdirtree( trailingslashit( $hmbkp_path ) . $file );
480
  }
481
 
533
 
534
  return true;
535
  }
536
+
537
+ /**
538
+ * List of schedules
539
+ *
540
+ * @return array
541
+ */
542
+ function hmbkp_get_cron_schedules() {
543
+
544
+ $schedules = wp_get_schedules();
545
+
546
+ // remove any schedule whose key is not prefixed with 'hmbkp_'
547
+ foreach ( $schedules as $key => $arr ) {
548
+ if ( ! preg_match( '/^hmbkp_/', $key ) )
549
+ unset( $schedules[$key] );
550
+ }
551
+
552
+ return $schedules;
553
+ }
554
+
555
+ /**
556
+ * @param string $type the type of the schedule
557
+ * @param array $times {
558
+ * An array of time arguments. Optional.
559
+ *
560
+ * @type int $minutes The minute to start the schedule on. Defaults to current time + 10 minutes. Accepts
561
+ * any valid `date( 'i' )` output.
562
+ * @type int $hours The hour to start the schedule on. Defaults to current time + 10 minutes. Accepts
563
+ * any valid `date( 'G' )` output.
564
+ * @type string $day_of_week The day of the week to start the schedule on. Defaults to current time + 10 minutes. Accepts
565
+ * any valid `date( 'l' )` output.
566
+ * @type int $day_of_month The day of the month to start the schedule on. Defaults to current time + 10 minutes. Accepts
567
+ * any valid `date( 'j' )` output.
568
+ * @type int $now The current time. Defaults to `time()`. Accepts any valid timestamp.
569
+ *
570
+ * }
571
+ * @return int $timestamp Returns the resulting timestamp on success and Int 0 on failure
572
+ */
573
+ function hmbkp_determine_start_time( $type, $times = array() ) {
574
+
575
+ // Default to in 10 minutes
576
+ if ( ! empty( $times['now'] ) ) {
577
+ $default_timestamp = $times['now'] + 600;
578
+
579
+ } else {
580
+ $default_timestamp = time() + 600;
581
+ }
582
+
583
+ $default_times = array(
584
+ 'minutes' => date( 'i', $default_timestamp ),
585
+ 'hours' => date( 'G', $default_timestamp ),
586
+ 'day_of_week' => date( 'l', $default_timestamp ),
587
+ 'day_of_month' => date( 'j', $default_timestamp ),
588
+ 'now' => time()
589
+ );
590
+
591
+ $args = wp_parse_args( $times, $default_times );
592
+
593
+ $schedule_start = '';
594
+
595
+ $intervals = HMBKP_Scheduled_Backup::get_cron_schedules();
596
+
597
+ // Allow the hours and minutes to be overwritten by a constant
598
+ if ( defined( 'HMBKP_SCHEDULE_TIME' ) && HMBKP_SCHEDULE_TIME ) {
599
+ $hm = HMBKP_SCHEDULE_TIME;
600
+ }
601
+
602
+ // The hour and minute that the schedule should start on
603
+ else {
604
+ $hm = $args['hours'] . ':' . $args['minutes'] . ':00';
605
+ }
606
+
607
+ switch ( $type ) {
608
+
609
+ case 'hmbkp_hourly' :
610
+ case 'hmbkp_daily' :
611
+ case 'hmbkp_twicedaily':
612
+
613
+ // The next occurance of the specified time
614
+ $schedule_start = $hm;
615
+ break;
616
+
617
+ case 'hmbkp_weekly' :
618
+ case 'hmbkp_fortnightly' :
619
+
620
+ // The next day of the week at the specified time
621
+ $schedule_start = $args['day_of_week'] . ' ' . $hm;
622
+ break;
623
+
624
+ case 'hmbkp_monthly' :
625
+
626
+ // The occurance of the time on the specified day of the month
627
+ $schedule_start = date( 'F', $args['now'] ) . ' ' . $args['day_of_month'] . ' ' . $hm;
628
+
629
+ // If we've already gone past that day this month then we'll need to start next month
630
+ if ( strtotime( $schedule_start, $args['now'] ) <= $args['now'] )
631
+ $schedule_start = date( 'F', strtotime( '+ 1 month', $args['now'] ) ) . ' ' . $args['day_of_month'] . ' ' . $hm;
632
+
633
+ // If that's still in the past then we'll need to jump to next year
634
+ if ( strtotime( $schedule_start, $args['now'] ) <= $args['now'] )
635
+ $schedule_start = date( 'F', strtotime( '+ 1 month', $args['now'] ) ) . ' ' . $args['day_of_month'] . ' ' . date( 'Y', strtotime( '+ 1 year', $args['now'] ) ) . ' ' . $hm;
636
+
637
+ break;
638
+ default :
639
+
640
+ return 0;
641
+
642
+ break;
643
+
644
+ }
645
+
646
+ $timestamp = strtotime( $schedule_start, $args['now'] );
647
+
648
+ // Convert to UTC
649
+ $timestamp -= get_option( 'gmt_offset' ) * 3600;
650
+
651
+ // If the scheduled time already passed then keep adding the interval until we get to a future date
652
+ while ( $timestamp <= $args['now'] ) {
653
+ $timestamp += $intervals[ $type ]['interval'];
654
+ }
655
+
656
+ return $timestamp;
657
+
658
+ }
functions/interface.php CHANGED
@@ -124,6 +124,19 @@ function hmbkp_admin_notices() {
124
 
125
  endif;
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  }
128
 
129
  add_action( 'admin_head', 'hmbkp_admin_notices' );
@@ -277,7 +290,10 @@ function hmbkp_schedule_actions( HMBKP_Scheduled_Backup $schedule ) {
277
  // Start output buffering
278
  ob_start(); ?>
279
 
280
- <span class="hmbkp-status"><?php echo $schedule->get_status() ? wp_kses_data( $schedule->get_status() ) : __( 'Starting Backup', 'hmbkp' ); ?> <a href="<?php echo esc_url( add_query_arg( array( 'action' => 'hmbkp_cancel', 'hmbkp_schedule_id' => $schedule->get_id() ), $settings_url ) ); ?>"><?php _e( 'cancel', 'hmbkp' ); ?></a></span>
 
 
 
281
 
282
  <div class="hmbkp-schedule-actions row-actions">
283
 
124
 
125
  endif;
126
 
127
+ $test_backup = new HMBKP_Scheduled_Backup( 'test_backup' );
128
+
129
+ if ( ! is_readable( $test_backup->get_root() ) ) :
130
+
131
+ function hmbkp_backup_root_unreadable_notice() {
132
+ $test_backup = new HMBKP_Scheduled_Backup( 'test_backup' );
133
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong>' . sprintf( __( 'Your backup root path %s isn\'t readable.', 'hmbkp' ), '<code>' . $test_backup->get_root() . '</code>' ) . '</p></div>';
134
+ }
135
+
136
+ add_action( 'admin_notices', 'hmbkp_backup_root_unreadable_notice' );
137
+
138
+ endif;
139
+
140
  }
141
 
142
  add_action( 'admin_head', 'hmbkp_admin_notices' );
290
  // Start output buffering
291
  ob_start(); ?>
292
 
293
+ <span class="hmbkp-status"<?php if ( $schedule->get_status() ) { ?> title="<?php printf( __( 'Started %s ago', 'hmbkp' ), human_time_diff( $schedule->get_schedule_running_start_time() ) ); ?>"<?php } ?>>
294
+ <?php echo $schedule->get_status() ? wp_kses_data( $schedule->get_status() ) : __( 'Starting Backup', 'hmbkp' ); ?>
295
+ <a href="<?php echo esc_url( add_query_arg( array( 'action' => 'hmbkp_cancel', 'hmbkp_schedule_id' => $schedule->get_id() ), $settings_url ) ); ?>"><?php _e( 'cancel', 'hmbkp' ); ?></a>
296
+ </span>
297
 
298
  <div class="hmbkp-schedule-actions row-actions">
299
 
hm-backup/hm-backup.php CHANGED
@@ -181,7 +181,7 @@ class HM_Backup {
181
  // Is shell_exec or escapeshellcmd or escapeshellarg disabled?
182
  if ( array_intersect( array( 'shell_exec', 'escapeshellarg', 'escapeshellcmd' ), array_map( 'trim', explode( ',', @ini_get( 'disable_functions' ) ) ) ) )
183
  return false;
184
-
185
  // Functions can also be disabled via suhosin
186
  if ( array_intersect( array( 'shell_exec', 'escapeshellarg', 'escapeshellcmd' ), array_map( 'trim', explode( ',', @ini_get( 'suhosin.executor.func.blacklist' ) ) ) ) )
187
  return false;
@@ -208,6 +208,11 @@ class HM_Backup {
208
 
209
  $home_path = ABSPATH;
210
 
 
 
 
 
 
211
  // If site_url contains home_url and they differ then assume WordPress is installed in a sub directory
212
  if ( $home_url !== $site_url && strpos( $site_url, $home_url ) === 0 )
213
  $home_path = trailingslashit( substr( self::conform_dir( ABSPATH ), 0, strrpos( self::conform_dir( ABSPATH ), str_replace( $home_url, '', $site_url ) ) ) );
@@ -509,10 +514,12 @@ class HM_Backup {
509
  '/opt/local/bin/mysqldump'
510
  );
511
 
512
- // Find the one which works
513
  foreach ( $mysqldump_locations as $location ) {
514
- if ( @is_executable( self::conform_dir( $location ) ) )
515
  $this->set_mysqldump_command_path( $location );
 
 
516
  }
517
 
518
  return $this->mysqldump_command_path;
@@ -570,10 +577,12 @@ class HM_Backup {
570
  '/opt/local/bin/zip'
571
  );
572
 
573
- // Find the one which works
574
  foreach ( $zip_locations as $location ) {
575
- if ( @is_executable( self::conform_dir( $location ) ) )
576
  $this->set_zip_command_path( $location );
 
 
577
  }
578
 
579
  return $this->zip_command_path;
181
  // Is shell_exec or escapeshellcmd or escapeshellarg disabled?
182
  if ( array_intersect( array( 'shell_exec', 'escapeshellarg', 'escapeshellcmd' ), array_map( 'trim', explode( ',', @ini_get( 'disable_functions' ) ) ) ) )
183
  return false;
184
+
185
  // Functions can also be disabled via suhosin
186
  if ( array_intersect( array( 'shell_exec', 'escapeshellarg', 'escapeshellcmd' ), array_map( 'trim', explode( ',', @ini_get( 'suhosin.executor.func.blacklist' ) ) ) ) )
187
  return false;
208
 
209
  $home_path = ABSPATH;
210
 
211
+ // Attempt to guess the home path based on the location of wp-config.php
212
+ if ( ! file_exists( ABSPATH . 'wp-config.php' ) ) {
213
+ $home_path = trailingslashit( dirname( ABSPATH ) );
214
+ }
215
+
216
  // If site_url contains home_url and they differ then assume WordPress is installed in a sub directory
217
  if ( $home_url !== $site_url && strpos( $site_url, $home_url ) === 0 )
218
  $home_path = trailingslashit( substr( self::conform_dir( ABSPATH ), 0, strrpos( self::conform_dir( ABSPATH ), str_replace( $home_url, '', $site_url ) ) ) );
514
  '/opt/local/bin/mysqldump'
515
  );
516
 
517
+ // Find the first one which works
518
  foreach ( $mysqldump_locations as $location ) {
519
+ if ( @is_executable( self::conform_dir( $location ) ) ) {
520
  $this->set_mysqldump_command_path( $location );
521
+ break; // Found one
522
+ }
523
  }
524
 
525
  return $this->mysqldump_command_path;
577
  '/opt/local/bin/zip'
578
  );
579
 
580
+ // Find the first one which works
581
  foreach ( $zip_locations as $location ) {
582
+ if ( @is_executable( self::conform_dir( $location ) ) ) {
583
  $this->set_zip_command_path( $location );
584
+ break; // Found one
585
+ }
586
  }
587
 
588
  return $this->zip_command_path;
readme.txt CHANGED
@@ -2,14 +2,14 @@
2
  Contributors: humanmade, willmot, pauldewouters, joehoyle, mattheu, tcrsavage, cuvelier
3
  Tags: back up, backup, backups, database, zip, db, files, archive, wp-cli, humanmade
4
  Requires at least: 3.7.1
5
- Tested up to: 3.8.1
6
- Stable tag: 2.5
7
 
8
- Simple automated back ups of your WordPress powered website.
9
 
10
  == Description ==
11
 
12
- [BackUpWordPress](http://bwp.hmn.md/?utm_source=wordpress-org&utm_medium=plugin-page&utm_campaign=freeplugin) will back up your entire site including your database and all your files on a schedule that suits you. Try it now to see how easy it is!
13
 
14
  = Features =
15
 
@@ -17,9 +17,9 @@ Simple automated back ups of your WordPress powered website.
17
  * Works in low memory, "shared host" environments.
18
  * Manage multiple schedules.
19
  * Option to have each backup file emailed to you.
20
- * Uses `zip` and `mysqldump` for faster back ups if they are available.
21
  * Works on Linux & Windows Server.
22
- * Exclude files and folders from your back ups.
23
  * Good support should you need help.
24
  * Translations for Spanish, German, Chinese, Romanian, Russian, Serbian, Lithuanian, Italian, Czech, Dutch, French, Basque.
25
 
@@ -49,7 +49,7 @@ Backups are stored on your server in `/wp-content/backups`, you can change the d
49
 
50
  **What if I want I want to back up my site to another destination?**
51
 
52
- BackUpWordPress Pro supports Dropbox, Google Drive, Amazon S3, Rackspace, Azure, DreamObjects and FTP/SFTP. Check it out here: [http://bwp.hmn.md](http://bwp.hmn.md/?utm_source=wordpress-org&utm_medium=plugin-page&utm_campaign=freeplugin)
53
 
54
  **How do I restore my site from a backup?**
55
 
@@ -107,6 +107,31 @@ You can also tweet <a href="http://twitter.com/humanmadeltd">@humanmadeltd</a> o
107
 
108
  == Changelog ==
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  #### 2.5
111
 
112
  * BackUpWordPress now requires WordPress 3.7.1 as a minimum.
2
  Contributors: humanmade, willmot, pauldewouters, joehoyle, mattheu, tcrsavage, cuvelier
3
  Tags: back up, backup, backups, database, zip, db, files, archive, wp-cli, humanmade
4
  Requires at least: 3.7.1
5
+ Tested up to: 3.9
6
+ Stable tag: 2.6
7
 
8
+ Simple automated backups of your WordPress powered website.
9
 
10
  == Description ==
11
 
12
+ [BackUpWordPress](https://bwp.hmn.md/?utm_source=wordpress-org&utm_medium=plugin-page&utm_campaign=freeplugin) will back up your entire site including your database and all your files on a schedule that suits you. Try it now to see how easy it is!
13
 
14
  = Features =
15
 
17
  * Works in low memory, "shared host" environments.
18
  * Manage multiple schedules.
19
  * Option to have each backup file emailed to you.
20
+ * Uses `zip` and `mysqldump` for faster backups if they are available.
21
  * Works on Linux & Windows Server.
22
+ * Exclude files and folders from your backups.
23
  * Good support should you need help.
24
  * Translations for Spanish, German, Chinese, Romanian, Russian, Serbian, Lithuanian, Italian, Czech, Dutch, French, Basque.
25
 
49
 
50
  **What if I want I want to back up my site to another destination?**
51
 
52
+ BackUpWordPress Pro supports Dropbox, Google Drive, Amazon S3, Rackspace, Azure, DreamObjects and FTP/SFTP. Check it out here: [https://bwp.hmn.md](http://bwp.hmn.md/?utm_source=wordpress-org&utm_medium=plugin-page&utm_campaign=freeplugin)
53
 
54
  **How do I restore my site from a backup?**
55
 
107
 
108
  == Changelog ==
109
 
110
+ #### 2.6
111
+
112
+ * It's now possible to choose the time and day that your schedule will run on.
113
+ * Introduces several new unit tests around schedule timings.
114
+ * Fixes a bug that could cause the hourly schedule to run constantly.
115
+ * Improved the layout of the Constants help panel.
116
+ * If the backup root directory is unreadable then the plugin will no longer function.
117
+ * Update the backups table match the standard WordPress table styles.
118
+ * Improved styling for the settings dialogue.
119
+ * Improved styling for the Server Info help tab.
120
+ * /s/back ups/backups.
121
+ * Remove Deprecated call to `screen_icon`.
122
+ * Updated French translation.
123
+ * Update the `WP CLI` command to use the new method for registering command.
124
+ * Reload the schedules when re-setting up the default schedules so they show up straight away.
125
+ * s/dpesnt't/doesn't.
126
+ * Only show the estimated total schedule size when editing an existing schedule.
127
+ * Stop stripping 0 from the minutes on hourly backups so that backups at 10 (& 20, etc.) past the hour correctly show.
128
+ * Disable buttons whilst ajax requests are running.
129
+ * Move spinners outside the buttons as they didn't look very good inside.
130
+ * Improve the detection of the home path on multisite installs which have WordPress in a subdirectory.
131
+ * Track the time that the running backup is started and display how long a backup has been running for.
132
+ * Fix an issue that meant it wasn't possible to run multiple manual backups at the same time.
133
+ * Many other minor improvements.
134
+
135
  #### 2.5
136
 
137
  * BackUpWordPress now requires WordPress 3.7.1 as a minimum.
uninstall.php CHANGED
@@ -3,9 +3,6 @@
3
  if ( ! defined( 'HMBKP_PLUGIN_PATH' ) )
4
  define( 'HMBKP_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
5
 
6
- if ( ! defined( 'HMBKP_SCHEDULE_TIME' ) )
7
- define( 'HMBKP_SCHEDULE_TIME', '11pm' );
8
-
9
  // Load the schedules
10
  require_once( HMBKP_PLUGIN_PATH . 'hm-backup/hm-backup.php' );
11
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-services.php' );
@@ -24,4 +21,4 @@ hmbkp_rmdirtree( hmbkp_path() );
24
 
25
  // Remove all the options
26
  foreach ( array( 'hmbkp_enable_support', 'hmbkp_plugin_version', 'hmbkp_path', 'hmbkp_default_path' ) as $option )
27
- delete_option( $option );
3
  if ( ! defined( 'HMBKP_PLUGIN_PATH' ) )
4
  define( 'HMBKP_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
5
 
 
 
 
6
  // Load the schedules
7
  require_once( HMBKP_PLUGIN_PATH . 'hm-backup/hm-backup.php' );
8
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-services.php' );
21
 
22
  // Remove all the options
23
  foreach ( array( 'hmbkp_enable_support', 'hmbkp_plugin_version', 'hmbkp_path', 'hmbkp_default_path' ) as $option )
24
+ delete_option( $option );