BackUpWordPress - Version 3.1.2

Version Description

= 3.0.4 =

  • Fixes a few minor bugs. Immediate update is recommended.

= 3.0.2 =

  • Important: we have dropped support for PHP 5.2, you will not be able to activate BackUpWordPress on a server running PHP versions older than PHP 5.3.29

= 3.0.1 =

  • This is a critical update. Fixes a bug in the core backup library. Please update immediately.
Download this release

Release Info

Developer pauldewouters
Plugin Icon 128x128 BackUpWordPress
Version 3.1.2
Comparing to
See all releases

Code changes from version 3.1.1 to 3.1.2

admin/actions.php CHANGED
@@ -7,7 +7,7 @@ function hmbkp_request_delete_backup() {
7
 
8
  check_admin_referer( 'hmbkp_delete_backup', 'hmbkp_delete_backup_nonce' );
9
 
10
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( urldecode( $_GET['hmbkp_schedule_id'] ) ) );
11
 
12
  $deleted = $schedule->delete_backup( sanitize_text_field( base64_decode( $_GET['hmbkp_backup_archive'] ) ) );
13
 
@@ -45,7 +45,7 @@ function hmbkp_request_delete_schedule() {
45
 
46
  check_admin_referer( 'hmbkp_delete_schedule', 'hmbkp_delete_schedule_nonce' );
47
 
48
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( urldecode( $_GET['hmbkp_schedule_id'] ) ) );
49
  $schedule->cancel( true );
50
 
51
  wp_safe_redirect( hmbkp_get_settings_url(), 303 );
@@ -89,15 +89,15 @@ function hmbkp_request_do_backup() {
89
 
90
  ignore_user_abort( true );
91
 
92
- HMBKP_Path::get_instance()->cleanup();
93
 
94
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( urldecode( $_GET['hmbkp_schedule_id'] ) ) );
95
 
96
  $schedule->run();
97
 
98
- HMBKP_Notices::get_instance()->clear_all_notices();
99
 
100
- $errors = array_merge( $schedule->get_errors(), $schedule->get_warnings() );
101
 
102
  $error_message = '';
103
 
@@ -105,7 +105,7 @@ function hmbkp_request_do_backup() {
105
  $error_message .= implode( "\n\r", $error_set );
106
  }
107
 
108
- if ( $error_message && file_exists( $schedule->get_archive_filepath() ) && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
109
  $error_message .= ' HMBKP_SUCCESS';
110
  }
111
 
@@ -138,13 +138,13 @@ function hmbkp_request_download_backup() {
138
  return;
139
  }
140
 
141
- $url = str_replace( HM_Backup::conform_dir( HM_Backup::get_home_path() ), home_url(), trailingslashit( dirname( sanitize_text_field( base64_decode( $_GET['hmbkp_backup_archive'] ) ) ) ) ) . urlencode( pathinfo( sanitize_text_field( base64_decode( $_GET['hmbkp_backup_archive'] ) ), PATHINFO_BASENAME ) );
142
 
143
  global $is_apache;
144
 
145
  if ( $is_apache ) {
146
 
147
- HMBKP_Path::get_instance()->protect_path( 'reset' );
148
 
149
  $url = add_query_arg( 'key', HMBKP_SECURE_KEY, $url );
150
 
@@ -164,7 +164,7 @@ function hmbkp_request_cancel_backup() {
164
 
165
  check_admin_referer( 'hmbkp_request_cancel_backup', 'hmbkp-request_cancel_backup_nonce' );
166
 
167
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( urldecode( $_GET['hmbkp_schedule_id'] ) ) );
168
 
169
  // Delete the running backup
170
  if ( $schedule->get_running_backup_filename() && file_exists( trailingslashit( hmbkp_path() ) . $schedule->get_running_backup_filename() ) ) {
@@ -175,7 +175,7 @@ function hmbkp_request_cancel_backup() {
175
  unlink( $schedule->get_schedule_running_path() );
176
  }
177
 
178
- HMBKP_Path::get_instance()->cleanup();
179
 
180
  wp_safe_redirect( hmbkp_get_settings_url(), 303 );
181
 
@@ -191,9 +191,9 @@ function hmbkp_dismiss_error() {
191
 
192
  check_admin_referer( 'hmbkp_dismiss_error', 'hmbkp_dismiss_error_nonce' );
193
 
194
- HMBKP_Path::get_instance()->cleanup();
195
 
196
- HMBKP_Notices::get_instance()->clear_all_notices();
197
 
198
  wp_safe_redirect( wp_get_referer(), 303 );
199
 
@@ -215,25 +215,23 @@ function hmbkp_edit_schedule_services_submit() {
215
  wp_die( __( 'The schedule ID was not provided. Aborting.', 'backupwordpress' ) );
216
  }
217
 
218
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( $_POST['hmbkp_schedule_id'] ) );
219
 
220
  hmbkp_clear_settings_errors();
221
 
222
  $errors = array();
223
 
224
  // Save the service options
225
- foreach ( HMBKP_Services::get_services( $schedule ) as $service ) {
226
  $errors = array_merge( $errors, $service->save() );
227
  }
228
 
229
  $schedule->save();
230
 
231
  if ( $errors ) {
232
-
233
  foreach ( $errors as $error ) {
234
  hmbkp_add_settings_error( $error );
235
  }
236
-
237
  }
238
 
239
  wp_safe_redirect( wp_get_referer(), '303' );
@@ -255,7 +253,7 @@ function hmbkp_edit_schedule_submit() {
255
  die;
256
  }
257
 
258
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( $_POST['hmbkp_schedule_id'] ) );
259
 
260
  hmbkp_clear_settings_errors();
261
 
@@ -393,7 +391,7 @@ function hmbkp_edit_schedule_submit() {
393
  }
394
 
395
  // Save the service options
396
- foreach ( HMBKP_Services::get_services( $schedule ) as $service ) {
397
  $errors = array_merge( $errors, $service->save() );
398
  }
399
 
@@ -460,9 +458,9 @@ function hmbkp_add_exclude_rule() {
460
  return;
461
  }
462
 
463
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( $_GET['hmbkp_schedule_id'] ) );
464
 
465
- $exclude_rule = str_ireplace( $schedule->get_root(), '', sanitize_text_field( $_GET['hmbkp_exclude_pathname'] ) );
466
 
467
  $schedule->set_excludes( $exclude_rule, true );
468
 
@@ -489,7 +487,7 @@ function hmbkp_remove_exclude_rule() {
489
  die;
490
  }
491
 
492
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( $_GET['hmbkp_schedule_id'] ) );
493
 
494
  $excludes = $schedule->get_excludes();
495
 
@@ -506,7 +504,7 @@ add_action( 'admin_post_hmbkp_remove_exclude_rule', 'hmbkp_remove_exclude_rule'
506
 
507
  /**
508
  *
509
- * @param null $pathname
510
  */
511
  function hmbkp_recalculate_directory_filesize() {
512
 
@@ -514,10 +512,6 @@ function hmbkp_recalculate_directory_filesize() {
514
  return;
515
  }
516
 
517
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( $_GET['hmbkp_schedule_id'] ) );
518
-
519
- $directory = sanitize_text_field( $_GET['hmbkp_recalculate_directory_filesize'] );
520
-
521
  // Delete the cached directory size
522
  delete_transient( 'hmbkp_directory_filesizes' );
523
 
@@ -537,23 +531,22 @@ function hmbkp_calculate_site_size() {
537
 
538
  if ( isset( $_GET['hmbkp_schedule_id'] ) ) {
539
 
540
- $current_schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( $_GET['hmbkp_schedule_id'] ) );
541
 
542
  } else {
543
 
544
  // Refresh the schedules from the database to make sure we have the latest changes
545
- HMBKP_Schedules::get_instance()->refresh_schedules();
546
 
547
- $schedules = HMBKP_Schedules::get_instance()->get_schedules();
548
 
549
  $current_schedule = reset( $schedules );
550
 
551
  }
552
 
553
  if ( ! $current_schedule->is_site_size_cached() ) {
554
- // Start calculating
555
- $root = new SplFileInfo( $current_schedule->get_root() );
556
- $size = $current_schedule->filesize( $root );
557
  }
558
 
559
  }
@@ -568,7 +561,7 @@ function hmbkp_heartbeat_received( $response, $data ) {
568
 
569
  if ( ! empty( $data['hmbkp_schedule_id'] ) ) {
570
 
571
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( urldecode( $data['hmbkp_schedule_id'] ) ) );
572
 
573
  if ( ! empty( $data['hmbkp_is_in_progress'] ) ) {
574
 
@@ -617,7 +610,7 @@ function hmbkp_display_error_and_offer_to_email_it() {
617
 
618
  $errors = explode( "\n", wp_strip_all_tags( stripslashes( $_POST['hmbkp_error'] ) ) );
619
 
620
- HMBKP_Notices::get_instance()->set_notices( 'backup_errors', $errors );
621
 
622
  wp_send_json_success( wp_get_referer() );
623
 
@@ -669,7 +662,7 @@ function hmbkp_ajax_is_backup_in_progress() {
669
  die;
670
  }
671
 
672
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( urldecode( $_POST['hmbkp_schedule_id'] ) ) );
673
 
674
  if ( ! $schedule->get_status() ) {
675
  echo 0;
@@ -693,7 +686,7 @@ function hmbkp_ajax_calculate_backup_size() {
693
  die;
694
  }
695
 
696
- $schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( urldecode( $_POST['hmbkp_schedule_id'] ) ) );
697
 
698
  $recalculate_filesize = true;
699
 
7
 
8
  check_admin_referer( 'hmbkp_delete_backup', 'hmbkp_delete_backup_nonce' );
9
 
10
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( urldecode( $_GET['hmbkp_schedule_id'] ) ) );
11
 
12
  $deleted = $schedule->delete_backup( sanitize_text_field( base64_decode( $_GET['hmbkp_backup_archive'] ) ) );
13
 
45
 
46
  check_admin_referer( 'hmbkp_delete_schedule', 'hmbkp_delete_schedule_nonce' );
47
 
48
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( urldecode( $_GET['hmbkp_schedule_id'] ) ) );
49
  $schedule->cancel( true );
50
 
51
  wp_safe_redirect( hmbkp_get_settings_url(), 303 );
89
 
90
  ignore_user_abort( true );
91
 
92
+ HM\BackUpWordPress\Path::get_instance()->cleanup();
93
 
94
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( urldecode( $_GET['hmbkp_schedule_id'] ) ) );
95
 
96
  $schedule->run();
97
 
98
+ HM\BackUpWordPress\Notices::get_instance()->clear_all_notices();
99
 
100
+ $errors = array_merge( $schedule->backup->get_errors(), $schedule->backup->get_warnings() );
101
 
102
  $error_message = '';
103
 
105
  $error_message .= implode( "\n\r", $error_set );
106
  }
107
 
108
+ if ( $error_message && file_exists( $schedule->backup->get_archive_filepath() ) && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
109
  $error_message .= ' HMBKP_SUCCESS';
110
  }
111
 
138
  return;
139
  }
140
 
141
+ $url = str_replace( HM\BackUpWordPress\Backup::conform_dir( HM\BackUpWordPress\Backup::get_home_path() ), home_url(), trailingslashit( dirname( sanitize_text_field( base64_decode( $_GET['hmbkp_backup_archive'] ) ) ) ) ) . urlencode( pathinfo( sanitize_text_field( base64_decode( $_GET['hmbkp_backup_archive'] ) ), PATHINFO_BASENAME ) );
142
 
143
  global $is_apache;
144
 
145
  if ( $is_apache ) {
146
 
147
+ HM\BackUpWordPress\Path::get_instance()->protect_path( 'reset' );
148
 
149
  $url = add_query_arg( 'key', HMBKP_SECURE_KEY, $url );
150
 
164
 
165
  check_admin_referer( 'hmbkp_request_cancel_backup', 'hmbkp-request_cancel_backup_nonce' );
166
 
167
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( urldecode( $_GET['hmbkp_schedule_id'] ) ) );
168
 
169
  // Delete the running backup
170
  if ( $schedule->get_running_backup_filename() && file_exists( trailingslashit( hmbkp_path() ) . $schedule->get_running_backup_filename() ) ) {
175
  unlink( $schedule->get_schedule_running_path() );
176
  }
177
 
178
+ HM\BackUpWordPress\Path::get_instance()->cleanup();
179
 
180
  wp_safe_redirect( hmbkp_get_settings_url(), 303 );
181
 
191
 
192
  check_admin_referer( 'hmbkp_dismiss_error', 'hmbkp_dismiss_error_nonce' );
193
 
194
+ HM\BackUpWordPress\Path::get_instance()->cleanup();
195
 
196
+ HM\BackUpWordPress\Notices::get_instance()->clear_all_notices();
197
 
198
  wp_safe_redirect( wp_get_referer(), 303 );
199
 
215
  wp_die( __( 'The schedule ID was not provided. Aborting.', 'backupwordpress' ) );
216
  }
217
 
218
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( $_POST['hmbkp_schedule_id'] ) );
219
 
220
  hmbkp_clear_settings_errors();
221
 
222
  $errors = array();
223
 
224
  // Save the service options
225
+ foreach ( HM\BackUpWordPress\Services::get_services( $schedule ) as $service ) {
226
  $errors = array_merge( $errors, $service->save() );
227
  }
228
 
229
  $schedule->save();
230
 
231
  if ( $errors ) {
 
232
  foreach ( $errors as $error ) {
233
  hmbkp_add_settings_error( $error );
234
  }
 
235
  }
236
 
237
  wp_safe_redirect( wp_get_referer(), '303' );
253
  die;
254
  }
255
 
256
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( $_POST['hmbkp_schedule_id'] ) );
257
 
258
  hmbkp_clear_settings_errors();
259
 
391
  }
392
 
393
  // Save the service options
394
+ foreach ( HM\BackUpWordPress\Services::get_services( $schedule ) as $service ) {
395
  $errors = array_merge( $errors, $service->save() );
396
  }
397
 
458
  return;
459
  }
460
 
461
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( $_GET['hmbkp_schedule_id'] ) );
462
 
463
+ $exclude_rule = str_ireplace( $schedule->backup->get_root(), '', sanitize_text_field( $_GET['hmbkp_exclude_pathname'] ) );
464
 
465
  $schedule->set_excludes( $exclude_rule, true );
466
 
487
  die;
488
  }
489
 
490
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( $_GET['hmbkp_schedule_id'] ) );
491
 
492
  $excludes = $schedule->get_excludes();
493
 
504
 
505
  /**
506
  *
507
+ * @param null
508
  */
509
  function hmbkp_recalculate_directory_filesize() {
510
 
512
  return;
513
  }
514
 
 
 
 
 
515
  // Delete the cached directory size
516
  delete_transient( 'hmbkp_directory_filesizes' );
517
 
531
 
532
  if ( isset( $_GET['hmbkp_schedule_id'] ) ) {
533
 
534
+ $current_schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( $_GET['hmbkp_schedule_id'] ) );
535
 
536
  } else {
537
 
538
  // Refresh the schedules from the database to make sure we have the latest changes
539
+ HM\BackUpWordPress\Schedules::get_instance()->refresh_schedules();
540
 
541
+ $schedules = HM\BackUpWordPress\Schedules::get_instance()->get_schedules();
542
 
543
  $current_schedule = reset( $schedules );
544
 
545
  }
546
 
547
  if ( ! $current_schedule->is_site_size_cached() ) {
548
+ $root = new SplFileInfo( $current_schedule->backup->get_root() );
549
+ $current_schedule->filesize( $root );
 
550
  }
551
 
552
  }
561
 
562
  if ( ! empty( $data['hmbkp_schedule_id'] ) ) {
563
 
564
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( urldecode( $data['hmbkp_schedule_id'] ) ) );
565
 
566
  if ( ! empty( $data['hmbkp_is_in_progress'] ) ) {
567
 
610
 
611
  $errors = explode( "\n", wp_strip_all_tags( stripslashes( $_POST['hmbkp_error'] ) ) );
612
 
613
+ HM\BackUpWordPress\Notices::get_instance()->set_notices( 'backup_errors', $errors );
614
 
615
  wp_send_json_success( wp_get_referer() );
616
 
662
  die;
663
  }
664
 
665
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( urldecode( $_POST['hmbkp_schedule_id'] ) ) );
666
 
667
  if ( ! $schedule->get_status() ) {
668
  echo 0;
686
  die;
687
  }
688
 
689
+ $schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( urldecode( $_POST['hmbkp_schedule_id'] ) ) );
690
 
691
  $recalculate_filesize = true;
692
 
admin/backups.php CHANGED
@@ -1,12 +1,12 @@
1
  <?php
2
 
3
  // Refresh the schedules from the database to make sure we have the latest changes
4
- HMBKP_Schedules::get_instance()->refresh_schedules();
5
 
6
- $schedules = HMBKP_Schedules::get_instance()->get_schedules();
7
 
8
  if ( ! empty( $_GET['hmbkp_schedule_id'] ) ) {
9
- $current_schedule = new HMBKP_Scheduled_Backup( sanitize_text_field( $_GET['hmbkp_schedule_id'] ) );
10
  } else {
11
  $current_schedule = reset( $schedules );
12
  } ?>
@@ -19,7 +19,7 @@ if ( ! empty( $_GET['hmbkp_schedule_id'] ) ) {
19
 
20
  <?php endforeach; ?>
21
 
22
- <a class="nav-tab<?php if ( ! HMBKP_Schedules::get_instance()->get_schedule( $current_schedule->get_id() ) ) { ?> nav-tab-active<?php } ?>" href="<?php echo esc_url( add_query_arg( array( 'hmbkp_add_schedule' => '1', 'action' => 'hmbkp_edit_schedule', 'hmbkp_schedule_id' => time(), 'hmbkp_panel' => 'hmbkp_edit_schedule_settings' ), HMBKP_ADMIN_URL ) ); ?>"> + <?php _e( 'add schedule', 'backupwordpress' ); ?></a>
23
 
24
  <?php if ( get_option( 'hmbkp_enable_support' ) ) { ?>
25
 
1
  <?php
2
 
3
  // Refresh the schedules from the database to make sure we have the latest changes
4
+ HM\BackUpWordPress\Schedules::get_instance()->refresh_schedules();
5
 
6
+ $schedules = HM\BackUpWordPress\Schedules::get_instance()->get_schedules();
7
 
8
  if ( ! empty( $_GET['hmbkp_schedule_id'] ) ) {
9
+ $current_schedule = new HM\BackUpWordPress\Scheduled_Backup( sanitize_text_field( $_GET['hmbkp_schedule_id'] ) );
10
  } else {
11
  $current_schedule = reset( $schedules );
12
  } ?>
19
 
20
  <?php endforeach; ?>
21
 
22
+ <a class="nav-tab<?php if ( ! HM\BackUpWordPress\Schedules::get_instance()->get_schedule( $current_schedule->get_id() ) ) { ?> nav-tab-active<?php } ?>" href="<?php echo esc_url( add_query_arg( array( 'hmbkp_add_schedule' => '1', 'action' => 'hmbkp_edit_schedule', 'hmbkp_schedule_id' => time(), 'hmbkp_panel' => 'hmbkp_edit_schedule_settings' ), HMBKP_ADMIN_URL ) ); ?>"> + <?php _e( 'add schedule', 'backupwordpress' ); ?></a>
23
 
24
  <?php if ( get_option( 'hmbkp_enable_support' ) ) { ?>
25
 
admin/constants.php CHANGED
@@ -94,7 +94,7 @@
94
  <p><?php printf( __( 'You\'ve set it to: %s', 'backupwordpress' ), '<code>' . HMBKP_ROOT . '</code>' ); ?></p>
95
  <?php } ?>
96
 
97
- <p><?php printf( __( 'The root directory that is backed up. Defaults to %s.', 'backupwordpress' ), '<code>' . HM_Backup::get_home_path() . '</code>' ); ?> <?php _e( 'e.g.', 'backupwordpress' ); ?> <code>define( 'HMBKP_ROOT', ABSPATH . 'wp/' );</code></p>
98
 
99
  </td>
100
 
@@ -116,8 +116,9 @@
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
 
94
  <p><?php printf( __( 'You\'ve set it to: %s', 'backupwordpress' ), '<code>' . HMBKP_ROOT . '</code>' ); ?></p>
95
  <?php } ?>
96
 
97
+ <p><?php printf( __( 'The root directory that is backed up. Defaults to %s.', 'backupwordpress' ), '<code>' . HM\BackUpWordPress\Backup::get_home_path() . '</code>' ); ?> <?php _e( 'e.g.', 'backupwordpress' ); ?> <code>define( 'HMBKP_ROOT', ABSPATH . 'wp/' );</code></p>
98
 
99
  </td>
100
 
116
 
117
  </tr>
118
 
119
+ <?php foreach ( HM\BackUpWordPress\Services::get_services() as $file => $service ) {
120
+ echo wp_kses_post( call_user_func( array( $service, 'constant' ) ) );
121
+ } ?>
122
 
123
  </table>
124
 
admin/enable-support.php CHANGED
@@ -6,7 +6,7 @@
6
 
7
  <div class="server-info">
8
 
9
- <?php foreach ( HMBKP_Requirements::get_requirement_groups() as $group ) : ?>
10
 
11
  <table class="fixed widefat">
12
 
@@ -18,7 +18,7 @@
18
 
19
  <tbody>
20
 
21
- <?php foreach ( HMBKP_Requirements::get_requirements( $group ) as $requirement ) : ?>
22
 
23
  <?php if ( ( is_string( $requirement->raw_result() ) && strlen( $requirement->result() ) < 20 ) || is_bool( $requirement->raw_result() ) ) { ?>
24
 
6
 
7
  <div class="server-info">
8
 
9
+ <?php foreach ( HM\BackUpWordPress\Requirements::get_requirement_groups() as $group ) : ?>
10
 
11
  <table class="fixed widefat">
12
 
18
 
19
  <tbody>
20
 
21
+ <?php foreach ( HM\BackUpWordPress\Requirements::get_requirements( $group ) as $requirement ) : ?>
22
 
23
  <?php if ( ( is_string( $requirement->raw_result() ) && strlen( $requirement->result() ) < 20 ) || is_bool( $requirement->raw_result() ) ) { ?>
24
 
admin/schedule-form-excludes.php CHANGED
@@ -10,7 +10,7 @@
10
 
11
  <?php foreach ( $schedule->get_excludes() as $key => $exclude ) :
12
 
13
- $exclude_path = new SplFileInfo( trailingslashit( $schedule->get_root() ) . ltrim( str_ireplace( $schedule->get_root(), '', $exclude ), '/' ) ); ?>
14
 
15
  <tr>
16
 
@@ -29,13 +29,13 @@
29
  </th>
30
 
31
  <td>
32
- <code><?php echo esc_html( str_ireplace( $schedule->get_root(), '', $exclude ) ); ?></code>
33
 
34
  </td>
35
 
36
  <td>
37
 
38
- <?php if ( ( $schedule->get_path() === untrailingslashit( $exclude ) ) || ( in_array( $exclude, $schedule->default_excludes() ) ) ) : ?>
39
 
40
  <?php _e( 'Default rule', 'backupwordpress' ); ?>
41
 
@@ -68,20 +68,20 @@
68
  <?php
69
 
70
  // The directory to display
71
- $directory = $schedule->get_root();
72
 
73
  if ( isset( $_GET['hmbkp_directory_browse'] ) ) {
74
 
75
  $untrusted_directory = urldecode( $_GET['hmbkp_directory_browse'] );
76
 
77
  // Only allow real sub directories of the site root to be browsed
78
- if ( strpos( $untrusted_directory, $schedule->get_root() ) !== false && is_dir( $untrusted_directory ) ) {
79
  $directory = $untrusted_directory;
80
  }
81
 
82
  }
83
 
84
- $exclude_string = $schedule->exclude_string( 'regex' );
85
 
86
  // Kick off a recursive filesize scan
87
  $files = $schedule->list_directory_by_total_filesize( $directory );
@@ -109,11 +109,11 @@
109
 
110
  <th scope="col">
111
 
112
- <?php if ( $schedule->get_root() !== $directory ) { ?>
113
 
114
- <a href="<?php echo remove_query_arg( 'hmbkp_directory_browse' ); ?>"><?php echo esc_html( $schedule->get_root() ); ?></a> <code>/</code>
115
 
116
- <?php $parents = array_filter( explode( '/', str_replace( trailingslashit( $schedule->get_root() ), '', trailingslashit( dirname( $directory ) ) ) ) );
117
 
118
  foreach ( $parents as $directory_basename ) { ?>
119
 
@@ -125,7 +125,7 @@
125
 
126
  <?php } else { ?>
127
 
128
- <?php echo esc_html( $schedule->get_root() ); ?>
129
 
130
  <?php } ?>
131
 
@@ -139,7 +139,7 @@
139
 
140
  <?php } else {
141
 
142
- $root = new SplFileInfo( $schedule->get_root() );
143
 
144
  $size = $schedule->filesize( $root );
145
 
@@ -155,7 +155,7 @@
155
 
156
  <?php echo esc_html( $size ); ?>
157
 
158
- <a class="dashicons dashicons-update" href="<?php echo wp_nonce_url( add_query_arg( 'hmbkp_recalculate_directory_filesize', urlencode( $schedule->get_root() ) ), 'hmbkp-recalculate_directory_filesize' ); ?>"><span><?php _e( 'Refresh', 'backupwordpress' ); ?></span></a>
159
 
160
  </code>
161
 
@@ -165,16 +165,16 @@
165
  <?php } ?>
166
 
167
  <td>
168
- <?php echo esc_html( substr( sprintf( '%o', fileperms( $schedule->get_root() ) ), -4 ) ); ?>
169
  </td>
170
 
171
  <td>
172
 
173
- <?php if ( is_link( $schedule->get_root() ) ) {
174
 
175
  _e( 'Symlink', 'backupwordpress' );
176
 
177
- } elseif ( is_dir( $schedule->get_root() ) ) {
178
 
179
  _e( 'Folder', 'backupwordpress' );
180
 
@@ -195,7 +195,7 @@
195
  $is_excluded = $is_unreadable = false;
196
 
197
  // Check if the file is excluded
198
- if ( $exclude_string && preg_match( '(' . $exclude_string . ')', str_ireplace( trailingslashit( $schedule->get_root() ), '', HM_Backup::conform_dir( $file->getPathname() ) ) ) ) {
199
  $is_excluded = true;
200
  }
201
 
10
 
11
  <?php foreach ( $schedule->get_excludes() as $key => $exclude ) :
12
 
13
+ $exclude_path = new SplFileInfo( trailingslashit( $schedule->backup->get_root() ) . ltrim( str_ireplace( $schedule->backup->get_root(), '', $exclude ), '/' ) ); ?>
14
 
15
  <tr>
16
 
29
  </th>
30
 
31
  <td>
32
+ <code><?php echo esc_html( str_ireplace( $schedule->backup->get_root(), '', $exclude ) ); ?></code>
33
 
34
  </td>
35
 
36
  <td>
37
 
38
+ <?php if ( ( hmbkp_path() === untrailingslashit( $exclude ) ) || ( in_array( $exclude, $schedule->default_excludes() ) ) ) : ?>
39
 
40
  <?php _e( 'Default rule', 'backupwordpress' ); ?>
41
 
68
  <?php
69
 
70
  // The directory to display
71
+ $directory = $schedule->backup->get_root();
72
 
73
  if ( isset( $_GET['hmbkp_directory_browse'] ) ) {
74
 
75
  $untrusted_directory = urldecode( $_GET['hmbkp_directory_browse'] );
76
 
77
  // Only allow real sub directories of the site root to be browsed
78
+ if ( strpos( $untrusted_directory, $schedule->backup->get_root() ) !== false && is_dir( $untrusted_directory ) ) {
79
  $directory = $untrusted_directory;
80
  }
81
 
82
  }
83
 
84
+ $exclude_string = $schedule->backup->exclude_string( 'regex' );
85
 
86
  // Kick off a recursive filesize scan
87
  $files = $schedule->list_directory_by_total_filesize( $directory );
109
 
110
  <th scope="col">
111
 
112
+ <?php if ( $schedule->backup->get_root() !== $directory ) { ?>
113
 
114
+ <a href="<?php echo remove_query_arg( 'hmbkp_directory_browse' ); ?>"><?php echo esc_html( $schedule->backup->get_root() ); ?></a> <code>/</code>
115
 
116
+ <?php $parents = array_filter( explode( '/', str_replace( trailingslashit( $schedule->backup->get_root() ), '', trailingslashit( dirname( $directory ) ) ) ) );
117
 
118
  foreach ( $parents as $directory_basename ) { ?>
119
 
125
 
126
  <?php } else { ?>
127
 
128
+ <?php echo esc_html( $schedule->backup->get_root() ); ?>
129
 
130
  <?php } ?>
131
 
139
 
140
  <?php } else {
141
 
142
+ $root = new SplFileInfo( $schedule->backup->get_root() );
143
 
144
  $size = $schedule->filesize( $root );
145
 
155
 
156
  <?php echo esc_html( $size ); ?>
157
 
158
+ <a class="dashicons dashicons-update" href="<?php echo wp_nonce_url( add_query_arg( 'hmbkp_recalculate_directory_filesize', urlencode( $schedule->backup->get_root() ) ), 'hmbkp-recalculate_directory_filesize' ); ?>"><span><?php _e( 'Refresh', 'backupwordpress' ); ?></span></a>
159
 
160
  </code>
161
 
165
  <?php } ?>
166
 
167
  <td>
168
+ <?php echo esc_html( substr( sprintf( '%o', fileperms( $schedule->backup->get_root() ) ), -4 ) ); ?>
169
  </td>
170
 
171
  <td>
172
 
173
+ <?php if ( is_link( $schedule->backup->get_root() ) ) {
174
 
175
  _e( 'Symlink', 'backupwordpress' );
176
 
177
+ } elseif ( is_dir( $schedule->backup->get_root() ) ) {
178
 
179
  _e( 'Folder', 'backupwordpress' );
180
 
195
  $is_excluded = $is_unreadable = false;
196
 
197
  // Check if the file is excluded
198
+ if ( $exclude_string && preg_match( '(' . $exclude_string . ')', str_ireplace( trailingslashit( $schedule->backup->get_root() ), '', HM\BackUpWordPress\Backup::conform_dir( $file->getPathname() ) ) ) ) {
199
  $is_excluded = true;
200
  }
201
 
admin/schedule-form.php CHANGED
@@ -173,7 +173,7 @@
173
 
174
  </tr>
175
 
176
- <?php foreach ( HMBKP_Services::get_services( $schedule ) as $service ) {
177
  $service->field();
178
  } ?>
179
 
173
 
174
  </tr>
175
 
176
+ <?php foreach ( HM\BackUpWordPress\Services::get_services( $schedule ) as $service ) {
177
  $service->field();
178
  } ?>
179
 
admin/schedule-sentence.php CHANGED
@@ -62,12 +62,13 @@ switch ( $schedule->get_reoccurrence() ) :
62
 
63
  default :
64
 
 
65
  $schedule->set_reoccurrence( 'manually' );
66
 
67
  endswitch;
68
 
69
  $server = '<span title="' . esc_attr( hmbkp_path() ) . '">' . __( 'this server', 'backupwordpress' ) . '</span>';
70
- $server = '<code>' . esc_attr( str_replace( $schedule->get_home_path(), '', hmbkp_path() ) ) . '</code>';
71
 
72
  // Backup to keep
73
  switch ( $schedule->get_max_backups() ) :
@@ -92,7 +93,7 @@ endswitch;
92
 
93
  $email_msg = $services = '';
94
 
95
- foreach ( HMBKP_Services::get_services( $schedule ) as $file => $service ) {
96
 
97
  if ( 'Email' === $service->name ) {
98
  $email_msg = wp_kses_post( $service->display() );
@@ -126,7 +127,7 @@ if ( ! empty( $services ) && count( $services ) > 1 ) {
126
 
127
  echo $sentence; ?>
128
 
129
- <?php if ( HMBKP_Schedules::get_instance()->get_schedule( $schedule->get_id() ) ) {
130
  hmbkp_schedule_status( $schedule );
131
  } ?>
132
 
@@ -140,11 +141,11 @@ if ( ! empty( $services ) && count( $services ) > 1 ) {
140
  * Returns a formatted string containing the calculated total site size or a message
141
  * to indicate it is being calculated.
142
  *
143
- * @param HMBKP_Scheduled_Backup $schedule
144
  *
145
  * @return string
146
  */
147
- function hmbkp_get_site_size_text( HMBKP_Scheduled_Backup $schedule ) {
148
 
149
  if ( isset( $_GET['hmbkp_add_schedule'] ) ) {
150
  return '';
62
 
63
  default :
64
 
65
+ $reoccurrence = __( 'manually', 'backupwordpress' );
66
  $schedule->set_reoccurrence( 'manually' );
67
 
68
  endswitch;
69
 
70
  $server = '<span title="' . esc_attr( hmbkp_path() ) . '">' . __( 'this server', 'backupwordpress' ) . '</span>';
71
+ $server = '<code>' . esc_attr( str_replace( HM\BackUpWordPress\Backup::get_home_path(), '', hmbkp_path() ) ) . '</code>';
72
 
73
  // Backup to keep
74
  switch ( $schedule->get_max_backups() ) :
93
 
94
  $email_msg = $services = '';
95
 
96
+ foreach ( HM\BackUpWordPress\Services::get_services( $schedule ) as $file => $service ) {
97
 
98
  if ( 'Email' === $service->name ) {
99
  $email_msg = wp_kses_post( $service->display() );
127
 
128
  echo $sentence; ?>
129
 
130
+ <?php if ( HM\BackUpWordPress\Schedules::get_instance()->get_schedule( $schedule->get_id() ) ) {
131
  hmbkp_schedule_status( $schedule );
132
  } ?>
133
 
141
  * Returns a formatted string containing the calculated total site size or a message
142
  * to indicate it is being calculated.
143
  *
144
+ * @param HM\BackUpWordPress\Scheduled_Backup $schedule
145
  *
146
  * @return string
147
  */
148
+ function hmbkp_get_site_size_text( HM\BackUpWordPress\Scheduled_Backup $schedule ) {
149
 
150
  if ( isset( $_GET['hmbkp_add_schedule'] ) ) {
151
  return '';
admin/schedule-settings.php CHANGED
@@ -1,4 +1,6 @@
1
- <?php if ( HMBKP_Schedules::get_instance()->get_schedule( $schedule->get_id() ) ) { ?>
 
 
2
 
3
  <div class="hmbkp-schedule-actions row-actions">
4
 
@@ -13,7 +15,7 @@
13
  <a href="<?php echo esc_url( add_query_arg( array( 'action' => 'hmbkp_edit_schedule', 'hmbkp_panel' => 'hmbkp_edit_schedule_excludes', 'hmbkp_schedule_id' => $schedule->get_id() ), hmbkp_get_settings_url() ) ); ?>"><?php _e( 'Excludes', 'backupwordpress' ); ?></a> |
14
  <?php endif; ?>
15
 
16
- <?php foreach ( HMBKP_Services::get_services( $schedule ) as $service ) :
17
 
18
  if ( ! $service->has_form() )
19
  continue; ?>
@@ -43,7 +45,7 @@
43
  } ?>
44
 
45
  <?php // Show the service form if we are viewing one
46
- foreach ( HMBKP_Services::get_services( $schedule ) as $service ) : ?>
47
 
48
  <?php if ( $_GET['action'] === 'hmbkp_edit_schedule' && $_GET['hmbkp_panel'] === 'hmbkp_edit_schedule_settings_' . $service->get_slug() ) { ?>
49
 
1
+ <?php
2
+
3
+ if ( HM\BackUpWordPress\Schedules::get_instance()->get_schedule( $schedule->get_id() ) ) { ?>
4
 
5
  <div class="hmbkp-schedule-actions row-actions">
6
 
15
  <a href="<?php echo esc_url( add_query_arg( array( 'action' => 'hmbkp_edit_schedule', 'hmbkp_panel' => 'hmbkp_edit_schedule_excludes', 'hmbkp_schedule_id' => $schedule->get_id() ), hmbkp_get_settings_url() ) ); ?>"><?php _e( 'Excludes', 'backupwordpress' ); ?></a> |
16
  <?php endif; ?>
17
 
18
+ <?php foreach ( HM\BackUpWordPress\Services::get_services( $schedule ) as $service ) :
19
 
20
  if ( ! $service->has_form() )
21
  continue; ?>
45
  } ?>
46
 
47
  <?php // Show the service form if we are viewing one
48
+ foreach ( HM\BackUpWordPress\Services::get_services( $schedule ) as $service ) : ?>
49
 
50
  <?php if ( $_GET['action'] === 'hmbkp_edit_schedule' && $_GET['hmbkp_panel'] === 'hmbkp_edit_schedule_settings_' . $service->get_slug() ) { ?>
51
 
admin/server-info.php CHANGED
@@ -1,4 +1,6 @@
1
- <?php foreach ( HMBKP_Requirements::get_requirement_groups() as $group ) : ?>
 
 
2
 
3
  <h3><?php echo ucwords( $group ); ?></h3>
4
 
@@ -6,7 +8,7 @@
6
 
7
  <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
 
@@ -69,6 +71,6 @@
69
 
70
  <?php endforeach;
71
 
72
- foreach ( HMBKP_Services::get_services() as $file => $service ) {
73
  echo wp_kses_post( call_user_func( array( $service, 'intercom_data_html' ) ) );
74
  }
1
+ <?php
2
+
3
+ foreach ( HM\BackUpWordPress\Requirements::get_requirement_groups() as $group ) : ?>
4
 
5
  <h3><?php echo ucwords( $group ); ?></h3>
6
 
8
 
9
  <tbody>
10
 
11
+ <?php foreach ( HM\BackUpWordPress\Requirements::get_requirements( $group ) as $requirement ) : ?>
12
 
13
  <?php if ( ( is_string( $requirement->raw_result() ) && strlen( $requirement->result() ) < 20 ) || is_bool( $requirement->raw_result() ) ) : ?>
14
 
71
 
72
  <?php endforeach;
73
 
74
+ foreach ( HM\BackUpWordPress\Services::get_services() as $file => $service ) {
75
  echo wp_kses_post( call_user_func( array( $service, 'intercom_data_html' ) ) );
76
  }
backupwordpress.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: BackUpWordPress
4
  Plugin URI: http://bwp.hmn.md/
5
  Description: Simple automated backups of your WordPress powered website. Once activated you'll find me under <strong>Tools &rarr; Backups</strong>. On multisite, you'll find me under the Network Settings menu.
6
- Version: 3.1.1
7
  Author: Human Made Limited
8
  Author URI: http://hmn.md/
9
  License: GPL-2.0+
@@ -31,40 +31,41 @@ along with this program; if not, write to the Free Software
31
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32
  */
33
 
34
- include_once( dirname( __FILE__ ) . '/classes/class-setup.php' );
35
 
36
- register_activation_hook( __FILE__, array( 'BackUpWordPress_Setup', 'activate' ) );
37
- register_deactivation_hook( __FILE__, array( 'BackUpWordPress_Setup', 'deactivate' ) );
 
 
38
 
39
  /**
40
- * Class BackUpWordPress_Plugin
41
  */
42
- class BackUpWordPress_Plugin {
43
 
44
- const PLUGIN_VERSION = '3.1.1';
45
 
46
  /**
47
- * @var BackUpWordPress_Plugin The singleton instance.
48
  */
49
  private static $instance;
50
 
51
  /**
52
- * Instantiates a new BackUpWordPress_Plugin object.
53
  */
54
  private function __construct() {
55
-
56
  add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );
57
  }
58
 
59
  /**
60
  * Insures we always return the same object.
61
  *
62
- * @return BackUpWordPress_Plugin
63
  */
64
  public static function get_instance() {
65
 
66
- if ( ! ( self::$instance instanceof BackUpWordPress_Plugin ) ) {
67
- self::$instance = new BackUpWordPress_Plugin();
68
  }
69
 
70
  return self::$instance;
@@ -94,11 +95,9 @@ class BackUpWordPress_Plugin {
94
 
95
  public function maybe_self_deactivate() {
96
 
97
- if ( ! BackUpWordPress_Setup::meets_requirements() ) {
98
-
99
- add_action( 'admin_init', array( 'BackUpWordPress_Setup', 'self_deactivate' ) );
100
-
101
- add_action( 'admin_notices', array( 'BackUpWordPress_Setup', 'display_admin_notices' ) );
102
  }
103
 
104
  }
@@ -125,17 +124,12 @@ class BackUpWordPress_Plugin {
125
  }
126
 
127
  if ( ! defined( 'HMBKP_ADMIN_URL' ) ) {
128
-
129
  $page = is_multisite() ? network_admin_url( 'settings.php' ) : admin_url( 'tools.php' );
130
-
131
  define( 'HMBKP_ADMIN_URL', add_query_arg( 'page', HMBKP_PLUGIN_SLUG, $page ) );
132
-
133
  }
134
 
135
  if ( ! defined( 'HMBKP_ADMIN_PAGE' ) ) {
136
-
137
  $prefix = is_multisite() ? 'settings_page_' : 'tools_page_';
138
-
139
  define( 'HMBKP_ADMIN_PAGE', $prefix . HMBKP_PLUGIN_SLUG );
140
  }
141
 
@@ -154,41 +148,41 @@ class BackUpWordPress_Plugin {
154
  require_once( HMBKP_PLUGIN_PATH . 'admin/menu.php' );
155
  require_once( HMBKP_PLUGIN_PATH . 'admin/actions.php' );
156
 
157
- // Load hm-backup
158
- if ( ! class_exists( 'HM_Backup' ) ) {
159
- require_once( HMBKP_PLUGIN_PATH . 'hm-backup/hm-backup.php' );
160
- }
161
-
162
  // Load Backdrop if necessary.
163
  if ( ! class_exists( 'HM_Backdrop_Task' ) ) {
164
  require_once( HMBKP_PLUGIN_PATH . 'backdrop/hm-backdrop.php' );
165
  }
166
 
167
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-requirements.php' );
 
 
 
168
 
169
- require_once( HMBKP_PLUGIN_PATH . 'classes/class-hmbkp-path.php' );
 
170
 
171
- // Load the schedules
172
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-schedule.php' );
173
- require_once( HMBKP_PLUGIN_PATH . 'classes/class-schedules.php' );
174
 
175
  // Load the core functions
176
  require_once( HMBKP_PLUGIN_PATH . 'functions/core.php' );
177
  require_once( HMBKP_PLUGIN_PATH . 'functions/interface.php' );
178
 
179
- // Load Services
180
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-services.php' );
 
181
 
182
  // Load the email service
183
- require_once( HMBKP_PLUGIN_PATH . 'classes/class-email.php' );
184
 
185
  // Load the webhook services
186
- require_once( HMBKP_PLUGIN_PATH . 'classes/class-webhooks.php' );
187
- require_once( HMBKP_PLUGIN_PATH . 'classes/class-webhook-wpremote.php' );
188
 
189
  // Load the wp cli command
190
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
191
- include( HMBKP_PLUGIN_PATH . 'classes/wp-cli.php' );
192
  }
193
 
194
  }
@@ -227,6 +221,7 @@ class BackUpWordPress_Plugin {
227
 
228
  $js_file = HMBKP_PLUGIN_URL . 'assets/hmbkp.min.js';
229
 
 
230
  if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
231
  $js_file = HMBKP_PLUGIN_URL . 'assets/hmbkp.js';
232
  }
@@ -293,7 +288,7 @@ class BackUpWordPress_Plugin {
293
  public function init() {
294
 
295
  // If we have multiple paths for some reason then clean them up
296
- HMBKP_Path::get_instance()->merge_existing_paths();
297
  }
298
 
299
  /**
@@ -304,21 +299,9 @@ class BackUpWordPress_Plugin {
304
  protected function generate_key() {
305
 
306
  $key = array( ABSPATH, time() );
 
307
 
308
- foreach (
309
- array(
310
- 'AUTH_KEY',
311
- 'SECURE_AUTH_KEY',
312
- 'LOGGED_IN_KEY',
313
- 'NONCE_KEY',
314
- 'AUTH_SALT',
315
- 'SECURE_AUTH_SALT',
316
- 'LOGGED_IN_SALT',
317
- 'NONCE_SALT',
318
- 'SECRET_KEY',
319
- ) as $constant
320
- ) {
321
-
322
  if ( defined( $constant ) ) {
323
  $key[] = constant( $constant );
324
  }
@@ -364,7 +347,7 @@ class BackUpWordPress_Plugin {
364
  return;
365
  }
366
 
367
- $schedules = HMBKP_Schedules::get_instance();
368
  $schedule = $schedules->get_schedule( $schedule_id );
369
 
370
  if ( ! $schedule ) {
@@ -407,16 +390,15 @@ class BackUpWordPress_Plugin {
407
  return;
408
  }
409
 
410
- foreach ( HMBKP_Requirements::get_requirement_groups() as $group ) {
411
-
412
- foreach ( HMBKP_Requirements::get_requirements( $group ) as $requirement ) {
413
 
 
 
414
  $info[ $requirement->name() ] = $requirement->result();
415
-
416
  }
417
  }
418
 
419
- foreach ( HMBKP_Services::get_services() as $file => $service ) {
420
  array_merge( $info, call_user_func( array( $service, 'intercom_data' ) ) );
421
  }
422
 
@@ -438,4 +420,4 @@ class BackUpWordPress_Plugin {
438
 
439
  }
440
 
441
- BackUpWordPress_Plugin::get_instance();
3
  Plugin Name: BackUpWordPress
4
  Plugin URI: http://bwp.hmn.md/
5
  Description: Simple automated backups of your WordPress powered website. Once activated you'll find me under <strong>Tools &rarr; Backups</strong>. On multisite, you'll find me under the Network Settings menu.
6
+ Version: 3.1.2
7
  Author: Human Made Limited
8
  Author URI: http://hmn.md/
9
  License: GPL-2.0+
31
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32
  */
33
 
34
+ namespace HM\BackUpWordPress;
35
 
36
+ require_once( plugin_dir_path( __FILE__ ) . 'classes/class-setup.php' );
37
+
38
+ register_activation_hook( __FILE__, array( 'HM\BackUpWordPress\Setup', 'activate' ) );
39
+ register_deactivation_hook( __FILE__, array( 'HM\BackUpWordPress\Setup', 'deactivate' ) );
40
 
41
  /**
42
+ * Class Plugin
43
  */
44
+ final class Plugin {
45
 
46
+ const PLUGIN_VERSION = '3.1.2';
47
 
48
  /**
49
+ * @var Plugin The singleton instance.
50
  */
51
  private static $instance;
52
 
53
  /**
54
+ * Instantiates a new Plugin object.
55
  */
56
  private function __construct() {
 
57
  add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );
58
  }
59
 
60
  /**
61
  * Insures we always return the same object.
62
  *
63
+ * @return Plugin
64
  */
65
  public static function get_instance() {
66
 
67
+ if ( ! ( self::$instance instanceof Plugin ) ) {
68
+ self::$instance = new Plugin();
69
  }
70
 
71
  return self::$instance;
95
 
96
  public function maybe_self_deactivate() {
97
 
98
+ if ( ! Setup::meets_requirements() ) {
99
+ add_action( 'admin_init', array( 'HM\BackUpWordPress\Setup', 'self_deactivate' ) );
100
+ add_action( 'admin_notices', array( 'HM\BackUpWordPress\Setup', 'display_admin_notices' ) );
 
 
101
  }
102
 
103
  }
124
  }
125
 
126
  if ( ! defined( 'HMBKP_ADMIN_URL' ) ) {
 
127
  $page = is_multisite() ? network_admin_url( 'settings.php' ) : admin_url( 'tools.php' );
 
128
  define( 'HMBKP_ADMIN_URL', add_query_arg( 'page', HMBKP_PLUGIN_SLUG, $page ) );
 
129
  }
130
 
131
  if ( ! defined( 'HMBKP_ADMIN_PAGE' ) ) {
 
132
  $prefix = is_multisite() ? 'settings_page_' : 'tools_page_';
 
133
  define( 'HMBKP_ADMIN_PAGE', $prefix . HMBKP_PLUGIN_SLUG );
134
  }
135
 
148
  require_once( HMBKP_PLUGIN_PATH . 'admin/menu.php' );
149
  require_once( HMBKP_PLUGIN_PATH . 'admin/actions.php' );
150
 
 
 
 
 
 
151
  // Load Backdrop if necessary.
152
  if ( ! class_exists( 'HM_Backdrop_Task' ) ) {
153
  require_once( HMBKP_PLUGIN_PATH . 'backdrop/hm-backdrop.php' );
154
  }
155
 
156
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-requirements.php' );
157
+ require_once( HMBKP_PLUGIN_PATH . 'classes/class-requirement.php' );
158
+
159
+ require_once( HMBKP_PLUGIN_PATH . 'classes/class-path.php' );
160
 
161
+ // Load the core backup class
162
+ require_once( HMBKP_PLUGIN_PATH . 'classes/class-backup.php' );
163
 
164
+ // Load the backup scheduling classes
165
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-schedule.php' );
166
+ require_once( plugin_dir_path( __FILE__ ) . 'classes/class-schedules.php' );
167
 
168
  // Load the core functions
169
  require_once( HMBKP_PLUGIN_PATH . 'functions/core.php' );
170
  require_once( HMBKP_PLUGIN_PATH . 'functions/interface.php' );
171
 
172
+ // Load the services
173
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-services.php' );
174
+ require_once( HMBKP_PLUGIN_PATH . 'classes/class-service.php' );
175
 
176
  // Load the email service
177
+ require_once( HMBKP_PLUGIN_PATH . 'classes/class-email-service.php' );
178
 
179
  // Load the webhook services
180
+ require_once( HMBKP_PLUGIN_PATH . 'classes/class-webhook-service.php' );
181
+ require_once( HMBKP_PLUGIN_PATH . 'classes/class-wpremote-webhook-service.php' );
182
 
183
  // Load the wp cli command
184
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
185
+ include( HMBKP_PLUGIN_PATH . 'classes/class-backupwordpress-wp-cli-command.php' );
186
  }
187
 
188
  }
221
 
222
  $js_file = HMBKP_PLUGIN_URL . 'assets/hmbkp.min.js';
223
 
224
+ // TODO shuold this also support WP_SCRIPT_DEBUG
225
  if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
226
  $js_file = HMBKP_PLUGIN_URL . 'assets/hmbkp.js';
227
  }
288
  public function init() {
289
 
290
  // If we have multiple paths for some reason then clean them up
291
+ Path::get_instance()->merge_existing_paths();
292
  }
293
 
294
  /**
299
  protected function generate_key() {
300
 
301
  $key = array( ABSPATH, time() );
302
+ $constants = array( 'AUTH_KEY', 'SECURE_AUTH_KEY', 'LOGGED_IN_KEY', 'NONCE_KEY', 'AUTH_SALT', 'SECURE_AUTH_SALT', 'LOGGED_IN_SALT', 'NONCE_SALT', 'SECRET_KEY' );
303
 
304
+ foreach ( $constants as $constant ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  if ( defined( $constant ) ) {
306
  $key[] = constant( $constant );
307
  }
347
  return;
348
  }
349
 
350
+ $schedules = Schedules::get_instance();
351
  $schedule = $schedules->get_schedule( $schedule_id );
352
 
353
  if ( ! $schedule ) {
390
  return;
391
  }
392
 
393
+ $info = array();
 
 
394
 
395
+ foreach ( Requirements::get_requirement_groups() as $group ) {
396
+ foreach ( Requirements::get_requirements( $group ) as $requirement ) {
397
  $info[ $requirement->name() ] = $requirement->result();
 
398
  }
399
  }
400
 
401
+ foreach ( Services::get_services() as $file => $service ) {
402
  array_merge( $info, call_user_func( array( $service, 'intercom_data' ) ) );
403
  }
404
 
420
 
421
  }
422
 
423
+ Plugin::get_instance();
classes/class-backup.php ADDED
@@ -0,0 +1,1784 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace HM\BackUpWordPress {
4
+
5
+ /**
6
+ * Generic file and database backup class
7
+ *
8
+ * @version 2.3
9
+ */
10
+ class Backup {
11
+
12
+ /**
13
+ * The backup type, must be either complete, file or database
14
+ *
15
+ * @string
16
+ */
17
+ private $type = '';
18
+
19
+ /**
20
+ * The filename of the backup file
21
+ *
22
+ * @string
23
+ */
24
+ private $archive_filename = '';
25
+
26
+ /**
27
+ * The filename of the database dump
28
+ *
29
+ * @string
30
+ */
31
+ private $database_dump_filename = '';
32
+
33
+ /**
34
+ * The path to the zip command
35
+ *
36
+ * @string
37
+ */
38
+ private $zip_command_path;
39
+
40
+ /**
41
+ * The path to the mysqldump command
42
+ *
43
+ * @string
44
+ */
45
+ private $mysqldump_command_path;
46
+
47
+ /**
48
+ * The filename of the existing backup file
49
+ *
50
+ * @string
51
+ */
52
+ private $existing_archive_filepath = '';
53
+
54
+ /**
55
+ * An array of exclude rules
56
+ *
57
+ * @array
58
+ */
59
+ private $excludes = array();
60
+
61
+ /**
62
+ * The path that should be backed up
63
+ *
64
+ * @var string
65
+ */
66
+ private $root = '';
67
+
68
+ /**
69
+ * Holds the current db connection
70
+ *
71
+ * @var resource
72
+ */
73
+ private $db;
74
+
75
+ /**
76
+ * An array of all the files in root
77
+ * excluding excludes and unreadable files
78
+ *
79
+ * @var array
80
+ */
81
+ private $files = array();
82
+
83
+ /**
84
+ * An array of all the files in root
85
+ * that match the exclude rules
86
+ *
87
+ * @var array
88
+ */
89
+ private $excluded_files = array();
90
+
91
+ /**
92
+ * An array of all the files in root
93
+ * that are unreadable
94
+ *
95
+ * @var array
96
+ */
97
+ private $unreadable_files = array();
98
+
99
+ /**
100
+ * An array of all the files in root
101
+ * that will be included in the backup
102
+ *
103
+ * @var array
104
+ */
105
+ protected $included_files = array();
106
+
107
+ /**
108
+ * Contains an array of errors
109
+ *
110
+ * @var mixed
111
+ */
112
+ private $errors = array();
113
+
114
+ /**
115
+ * Contains an array of warnings
116
+ *
117
+ * @var mixed
118
+ */
119
+ private $warnings = array();
120
+
121
+ /**
122
+ * The archive method used
123
+ *
124
+ * @var string
125
+ */
126
+ private $archive_method = '';
127
+
128
+ /**
129
+ * The mysqldump method used
130
+ *
131
+ * @var string
132
+ */
133
+ private $mysqldump_method = '';
134
+
135
+ /**
136
+ * @var bool
137
+ */
138
+ protected $mysqldump_verified = false;
139
+
140
+ /**
141
+ * @var bool
142
+ */
143
+ protected $archive_verified = false;
144
+
145
+ /**
146
+ * Hacky way to force a fallback to PclZip
147
+ *
148
+ * @todo re-factor out of this mess
149
+ * @var bool
150
+ */
151
+ public $skip_zip_archive = false;
152
+
153
+ /**
154
+ * @var string
155
+ */
156
+ protected $action_callback = '';
157
+
158
+ /**
159
+ * Check whether safe mode is active or not
160
+ *
161
+ * @param string $ini_get_callback
162
+ * @return bool
163
+ */
164
+ public static function is_safe_mode_active( $ini_get_callback = 'ini_get' ) {
165
+
166
+ $safe_mode = @call_user_func( $ini_get_callback, 'safe_mode' );
167
+
168
+ if ( $safe_mode && strtolower( $safe_mode ) != 'off' ) {
169
+ return true;
170
+ }
171
+
172
+ return false;
173
+
174
+ }
175
+
176
+ /**
177
+ * Check whether shell_exec has been disabled.
178
+ *
179
+ * @return bool
180
+ */
181
+ public static function is_shell_exec_available() {
182
+
183
+ // Are we in Safe Mode
184
+ if ( self::is_safe_mode_active() ) {
185
+ return false;
186
+ }
187
+
188
+ // Is shell_exec or escapeshellcmd or escapeshellarg disabled?
189
+ if ( self::is_function_disabled( 'suhosin.executor.func.blacklist' ) ) {
190
+ return false;
191
+ }
192
+
193
+ // Functions can also be disabled via suhosin
194
+ if ( self::is_function_disabled( 'disable_functions' ) ) {
195
+ return false;
196
+ }
197
+
198
+ // Can we issue a simple echo command?
199
+ if ( ! @shell_exec( 'echo backupwordpress' ) ) {
200
+ return false;
201
+ }
202
+
203
+ return true;
204
+
205
+ }
206
+
207
+ protected static function is_function_disabled( $ini_setting ) {
208
+
209
+ if ( array_intersect( array( 'shell_exec', 'escapeshellarg', 'escapeshellcmd' ), array_map( 'trim', explode( ',', @ini_get( $ini_setting ) ) ) ) ) {
210
+ return false;
211
+ }
212
+
213
+ }
214
+
215
+
216
+ /**
217
+ * Attempt to work out the root directory of the site, that
218
+ * is, the path equivelant of home_url().
219
+ *
220
+ * @return string $home_path
221
+ */
222
+ public static function get_home_path() {
223
+
224
+ $home_url = home_url();
225
+ $site_url = site_url();
226
+
227
+ $home_path = ABSPATH;
228
+
229
+ // If site_url contains home_url and they differ then assume WordPress is installed in a sub directory
230
+ if ( $home_url !== $site_url && strpos( $site_url, $home_url ) === 0 ) {
231
+ $home_path = trailingslashit( substr( self::conform_dir( ABSPATH ), 0, strrpos( self::conform_dir( ABSPATH ), str_replace( $home_url, '', $site_url ) ) ) );
232
+ }
233
+
234
+ return self::conform_dir( $home_path );
235
+
236
+ }
237
+
238
+
239
+ /**
240
+ * Sanitize a directory path
241
+ *
242
+ * @param string $dir
243
+ * @param bool $recursive
244
+ * @return string
245
+ */
246
+ public static function conform_dir( $dir, $recursive = false ) {
247
+
248
+ // Assume empty dir is root
249
+ if ( ! $dir ) {
250
+ $dir = '/';
251
+ }
252
+
253
+ // Replace single forward slash (looks like double slash because we have to escape it)
254
+ $dir = str_replace( '\\', '/', $dir );
255
+ $dir = str_replace( '//', '/', $dir );
256
+
257
+ // Remove the trailing slash
258
+ if ( $dir !== '/' ) {
259
+ $dir = untrailingslashit( $dir );
260
+ }
261
+
262
+ // Carry on until completely normalized
263
+ if ( ! $recursive && self::conform_dir( $dir, true ) != $dir ) {
264
+ return self::conform_dir( $dir );
265
+ }
266
+
267
+ return (string) $dir;
268
+
269
+ }
270
+
271
+ /**
272
+ * Sets up the default properties
273
+ */
274
+ public function __construct() {
275
+
276
+ // Raise the memory limit and max_execution time
277
+ @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
278
+ @set_time_limit( 0 );
279
+
280
+ // Set a custom error handler so we can track errors
281
+ set_error_handler( array( $this, 'error_handler' ) );
282
+
283
+ // Some properties can be overridden with defines
284
+ if ( defined( 'HMBKP_ROOT' ) && HMBKP_ROOT ) {
285
+ $this->set_root( HMBKP_ROOT );
286
+ }
287
+
288
+ if ( defined( 'HMBKP_EXCLUDE' ) && HMBKP_EXCLUDE ) {
289
+ $this->set_excludes( HMBKP_EXCLUDE, true );
290
+ }
291
+
292
+ if ( defined( 'HMBKP_MYSQLDUMP_PATH' ) ) {
293
+ $this->set_mysqldump_command_path( HMBKP_MYSQLDUMP_PATH );
294
+ }
295
+
296
+ if ( defined( 'HMBKP_ZIP_PATH' ) ) {
297
+ $this->set_zip_command_path( HMBKP_ZIP_PATH );
298
+ }
299
+
300
+ if ( defined( 'HMBKP_ZIP_PATH' ) && HMBKP_ZIP_PATH === 'PclZip' && $this->skip_zip_archive = true ) {
301
+ $this->set_zip_command_path( false );
302
+ }
303
+
304
+ }
305
+
306
+ /**
307
+ * Simple class wrapper for Path::get_path()
308
+ *
309
+ * @return string
310
+ */
311
+ private function get_path() {
312
+ return Path::get_instance()->get_path();
313
+ }
314
+
315
+ /**
316
+ * Get the full filepath to the archive file
317
+ *
318
+ * @return string
319
+ */
320
+ public function get_archive_filepath() {
321
+ return trailingslashit( $this->get_path() ) . $this->get_archive_filename();
322
+ }
323
+
324
+ /**
325
+ * Get the filename of the archive file
326
+ *
327
+ * @return string
328
+ */
329
+ public function get_archive_filename() {
330
+
331
+ if ( empty( $this->archive_filename ) ) {
332
+ $this->set_archive_filename( implode( '-', array( sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ), 'backup', current_time( 'Y-m-d-H-i-s' ) ) ) . '.zip' );
333
+ }
334
+
335
+ return $this->archive_filename;
336
+
337
+ }
338
+
339
+ /**
340
+ * Set the filename of the archive file
341
+ *
342
+ * @param string $filename
343
+ * @return \WP_Error|null
344
+ */
345
+ public function set_archive_filename( $filename ) {
346
+
347
+ if ( empty( $filename ) || ! is_string( $filename ) ) {
348
+ return new \WP_Error( 'invalid_file_name', __( 'archive filename must be a non empty string', 'backupwordpress' ) );
349
+ }
350
+
351
+ if ( pathinfo( $filename, PATHINFO_EXTENSION ) !== 'zip' ) {
352
+ return new \WP_Error( 'invalid_file_extension', sprintf( __( 'invalid file extension for archive filename <code>%s</code>', 'backupwordpress' ), $filename ) );
353
+ }
354
+
355
+ $this->archive_filename = strtolower( sanitize_file_name( remove_accents( $filename ) ) );
356
+
357
+ }
358
+
359
+ /**
360
+ * Get the full filepath to the database dump file.
361
+ *
362
+ * @return string
363
+ */
364
+ public function get_database_dump_filepath() {
365
+ return trailingslashit( $this->get_path() ) . $this->get_database_dump_filename();
366
+ }
367
+
368
+ /**
369
+ * Get the filename of the database dump file
370
+ *
371
+ * @return string
372
+ */
373
+ public function get_database_dump_filename() {
374
+
375
+ if ( empty( $this->database_dump_filename ) ) {
376
+ $this->set_database_dump_filename( 'database_' . DB_NAME . '.sql' );
377
+ }
378
+
379
+ return $this->database_dump_filename;
380
+
381
+ }
382
+
383
+ /**
384
+ * Set the filename of the database dump file
385
+ *
386
+ * @param string $filename
387
+ * @return \WP_Error|null
388
+ */
389
+ public function set_database_dump_filename( $filename ) {
390
+
391
+ if ( empty( $filename ) || ! is_string( $filename ) ) {
392
+ return new \WP_Error( 'invalid_file_name', __( 'database dump filename must be a non empty string', 'backupwordpress' ) );
393
+ }
394
+
395
+ if ( pathinfo( $filename, PATHINFO_EXTENSION ) !== 'sql' ) {
396
+ return new \WP_Error( 'invalid_file_extension', sprintf( __( 'invalid file extension for database dump filename <code>%s</code>', 'backupwordpress' ), $filename ) );
397
+ }
398
+
399
+ $this->database_dump_filename = strtolower( sanitize_file_name( remove_accents( $filename ) ) );
400
+
401
+ }
402
+
403
+ /**
404
+ * Get the root directory to backup from
405
+ *
406
+ * Defaults to the root of the path equivalent of your home_url
407
+ *
408
+ * @return string
409
+ */
410
+ public function get_root() {
411
+
412
+ if ( empty( $this->root ) ) {
413
+ $this->set_root( self::conform_dir( self::get_home_path() ) );
414
+ }
415
+
416
+ return $this->root;
417
+
418
+ }
419
+
420
+ /**
421
+ * Set the root directory to backup from
422
+ *
423
+ * @param string $path
424
+ * @return \WP_Error|null
425
+ */
426
+ public function set_root( $path ) {
427
+
428
+ if ( empty( $path ) || ! is_string( $path ) || ! is_dir( $path ) ) {
429
+ return new \WP_Error( 'invalid_directory_path', sprintf( __( 'Invalid root path <code>%s</code> must be a valid directory path', 'backupwordpress' ), $path ) );
430
+ }
431
+
432
+ $this->root = self::conform_dir( $path );
433
+
434
+ }
435
+
436
+ /**
437
+ * Get the filepath for the existing archive
438
+ *
439
+ * @return string
440
+ */
441
+ public function get_existing_archive_filepath() {
442
+ return $this->existing_archive_filepath;
443
+ }
444
+
445
+ /**
446
+ * Set the filepath for the existing archive
447
+ *
448
+ * @param string $existing_archive_filepath
449
+ * @return null
450
+ */
451
+ public function set_existing_archive_filepath( $existing_archive_filepath ) {
452
+
453
+ if ( empty( $existing_archive_filepath ) || ! is_string( $existing_archive_filepath ) ) {
454
+ return new \WP_Error( 'invalid_existing_archive_filepath', sprintf( __( 'Invalid existing archive filepath <code>%s</code> must be a non empty (string)', 'backupwordpress' ), $existing_archive_filepath ) );
455
+ }
456
+
457
+ $this->existing_archive_filepath = self::conform_dir( $existing_archive_filepath );
458
+
459
+ }
460
+
461
+ /**
462
+ * Get the archive method that was used for the backup
463
+ *
464
+ * Will be either zip, ZipArchive or PclZip
465
+ *
466
+ */
467
+ public function get_archive_method() {
468
+ return $this->archive_method;
469
+ }
470
+
471
+ /**
472
+ * Get the database dump method that was used for the backup
473
+ *
474
+ * Will be either mysqldump or mysqldump_fallback
475
+ *
476
+ */
477
+ public function get_mysqldump_method() {
478
+ return $this->mysqldump_method;
479
+ }
480
+
481
+ /**
482
+ * Get the backup type
483
+ *
484
+ * Defaults to complete
485
+ *
486
+ */
487
+ public function get_type() {
488
+
489
+ if ( empty( $this->type ) ) {
490
+ $this->set_type( 'complete' );
491
+ }
492
+
493
+ return $this->type;
494
+
495
+ }
496
+
497
+ /**
498
+ * Set the backup type
499
+ *
500
+ * $type must be one of complete, database or file
501
+ *
502
+ * @param string $type
503
+ * @return \WP_Error|null
504
+ */
505
+ public function set_type( $type ) {
506
+
507
+ if ( ! is_string( $type ) || ! in_array( $type, array( 'file', 'database', 'complete' ) ) ) {
508
+ return new \WP_Error( 'invalid_backup_type', sprintf( __( 'Invalid backup type <code>%s</code> must be one of (string) file, database or complete', 'backupwordpress' ), $type ) );
509
+ }
510
+
511
+ $this->type = $type;
512
+
513
+ }
514
+
515
+ /**
516
+ * Get the path to the mysqldump bin
517
+ *
518
+ * If not explicitly set will attempt to work
519
+ * it out by checking common locations
520
+ *
521
+ * @return string
522
+ */
523
+ public function get_mysqldump_command_path() {
524
+
525
+ // Check shell_exec is available
526
+ if ( ! self::is_shell_exec_available() ) {
527
+ return '';
528
+ }
529
+
530
+ // Return now if it's already been set
531
+ if ( isset( $this->mysqldump_command_path ) ) {
532
+ return $this->mysqldump_command_path;
533
+ }
534
+
535
+ $this->mysqldump_command_path = '';
536
+
537
+ // Does mysqldump work
538
+ if ( is_null( shell_exec( 'hash mysqldump 2>&1' ) ) ) {
539
+
540
+ // If so store it for later
541
+ $this->set_mysqldump_command_path( 'mysqldump' );
542
+
543
+ // And return now
544
+ return $this->mysqldump_command_path;
545
+
546
+ }
547
+
548
+ // List of possible mysqldump locations
549
+ $mysqldump_locations = array(
550
+ '/usr/local/bin/mysqldump',
551
+ '/usr/local/mysql/bin/mysqldump',
552
+ '/usr/mysql/bin/mysqldump',
553
+ '/usr/bin/mysqldump',
554
+ '/opt/local/lib/mysql6/bin/mysqldump',
555
+ '/opt/local/lib/mysql5/bin/mysqldump',
556
+ '/opt/local/lib/mysql4/bin/mysqldump',
557
+ '/xampp/mysql/bin/mysqldump',
558
+ '/Program Files/xampp/mysql/bin/mysqldump',
559
+ '/Program Files/MySQL/MySQL Server 6.0/bin/mysqldump',
560
+ '/Program Files/MySQL/MySQL Server 5.5/bin/mysqldump',
561
+ '/Program Files/MySQL/MySQL Server 5.4/bin/mysqldump',
562
+ '/Program Files/MySQL/MySQL Server 5.1/bin/mysqldump',
563
+ '/Program Files/MySQL/MySQL Server 5.0/bin/mysqldump',
564
+ '/Program Files/MySQL/MySQL Server 4.1/bin/mysqldump',
565
+ '/opt/local/bin/mysqldump'
566
+ );
567
+
568
+ // Find the first one which works
569
+ foreach ( $mysqldump_locations as $location ) {
570
+ if ( @is_executable( self::conform_dir( $location ) ) ) {
571
+ $this->set_mysqldump_command_path( $location );
572
+ break; // Found one
573
+ }
574
+ }
575
+
576
+ return $this->mysqldump_command_path;
577
+
578
+ }
579
+
580
+ /**
581
+ * Set the path to the mysqldump bin
582
+ *
583
+ * Setting the path to false will cause the database
584
+ * dump to use the php fallback
585
+ *
586
+ * @param mixed $path
587
+ */
588
+ public function set_mysqldump_command_path( $path ) {
589
+ $this->mysqldump_command_path = $path;
590
+ }
591
+
592
+ /**
593
+ * Get the path to the zip bin
594
+ *
595
+ * If not explicitly set will attempt to work
596
+ * it out by checking common locations
597
+ *
598
+ * @return string
599
+ */
600
+ public function get_zip_command_path() {
601
+
602
+ // Check shell_exec is available
603
+ if ( ! self::is_shell_exec_available() ) {
604
+ return '';
605
+ }
606
+
607
+ // Return now if it's already been set
608
+ if ( isset( $this->zip_command_path ) ) {
609
+ return $this->zip_command_path;
610
+ }
611
+
612
+ $this->zip_command_path = '';
613
+
614
+ // Does zip work
615
+ if ( is_null( shell_exec( 'hash zip 2>&1' ) ) ) {
616
+
617
+ // If so store it for later
618
+ $this->set_zip_command_path( 'zip' );
619
+
620
+ // And return now
621
+ return $this->zip_command_path;
622
+
623
+ }
624
+
625
+ // List of possible zip locations
626
+ $zip_locations = array(
627
+ '/usr/bin/zip',
628
+ '/opt/local/bin/zip'
629
+ );
630
+
631
+ // Find the first one which works
632
+ foreach ( $zip_locations as $location ) {
633
+ if ( @is_executable( self::conform_dir( $location ) ) ) {
634
+ $this->set_zip_command_path( $location );
635
+ break; // Found one
636
+ }
637
+ }
638
+
639
+ return $this->zip_command_path;
640
+
641
+ }
642
+
643
+ /**
644
+ * Set the path to the zip bin
645
+ *
646
+ * Setting the path to false will cause the database
647
+ * dump to use the php fallback
648
+ *
649
+ * @param mixed $path
650
+ */
651
+ public function set_zip_command_path( $path ) {
652
+ $this->zip_command_path = $path;
653
+ }
654
+
655
+ /**
656
+ * Fire actions for the various backup stages
657
+ *
658
+ * Callers can register callbacks to be called using `set_action_callback`
659
+ * Both the action and the instance on Backup are then passed to the callback function
660
+ *
661
+ * @see set_action_callback
662
+ * @param string $action The event to fire
663
+ */
664
+ protected function do_action( $action ) {
665
+
666
+ // If we have any callbacks then let's fire them
667
+ if ( ! empty( $this->action_callback ) ) {
668
+
669
+ // Order them by priority, lowest priority first
670
+ ksort( $this->action_callback );
671
+
672
+ foreach ( $this->action_callback as $priority ) {
673
+ foreach ( $priority as $callback ) {
674
+ call_user_func( $callback, $action, $this );
675
+ }
676
+ }
677
+
678
+ }
679
+
680
+ // Also fire a global WordPress action
681
+ do_action( $action, $this );
682
+
683
+ }
684
+
685
+ /**
686
+ * Allow the caller to set a callback function that will be invoked whenever
687
+ * an action fires
688
+ *
689
+ * @see do_action
690
+ * @see /do_action
691
+ * @param callable $callback The function or method to be called
692
+ * @param int $priority The priority of the callback
693
+ */
694
+ public function set_action_callback( $callback, $priority = 10 ) {
695
+ $this->action_callback[$priority][] = $callback;
696
+ }
697
+
698
+ /**
699
+ * Kick off a backup
700
+ *
701
+ * @todo should be renamed so it's not same as class
702
+ * @return null
703
+ */
704
+ public function backup() {
705
+
706
+ $this->do_action( 'hmbkp_backup_started' );
707
+
708
+ // Backup database
709
+ if ( $this->get_type() !== 'file' ) {
710
+ $this->dump_database();
711
+ }
712
+
713
+ // Zip everything up
714
+ $this->archive();
715
+
716
+ $this->do_action( 'hmbkp_backup_complete' );
717
+
718
+ }
719
+
720
+ /**
721
+ * Create the mysql backup
722
+ *
723
+ * Uses mysqldump if available, falls back to PHP
724
+ * if not.
725
+ *
726
+ */
727
+ public function dump_database() {
728
+
729
+ if ( $this->get_mysqldump_command_path() ) {
730
+ $this->mysqldump();
731
+ }
732
+
733
+ if ( empty( $this->mysqldump_verified ) ) {
734
+ $this->mysqldump_fallback();
735
+ }
736
+
737
+ $this->do_action( 'hmbkp_mysqldump_finished' );
738
+
739
+ }
740
+
741
+ public function mysqldump() {
742
+
743
+ $this->mysqldump_method = 'mysqldump';
744
+
745
+ $this->do_action( 'hmbkp_mysqldump_started' );
746
+
747
+ $host = explode( ':', DB_HOST );
748
+
749
+ $host = reset( $host );
750
+ $port = strpos( DB_HOST, ':' ) ? end( explode( ':', DB_HOST ) ) : '';
751
+
752
+ // Path to the mysqldump executable
753
+ $cmd = escapeshellarg( $this->get_mysqldump_command_path() );
754
+
755
+ // We don't want to create a new DB
756
+ $cmd .= ' --no-create-db';
757
+
758
+ // Allow lock-tables to be overridden
759
+ if ( ! defined( 'HMBKP_MYSQLDUMP_SINGLE_TRANSACTION' ) || HMBKP_MYSQLDUMP_SINGLE_TRANSACTION !== false ) {
760
+ $cmd .= ' --single-transaction';
761
+ }
762
+
763
+ // Make sure binary data is exported properly
764
+ $cmd .= ' --hex-blob';
765
+
766
+ // Username
767
+ $cmd .= ' -u ' . escapeshellarg( DB_USER );
768
+
769
+ // Don't pass the password if it's blank
770
+ if ( DB_PASSWORD ) {
771
+ $cmd .= ' -p' . escapeshellarg( DB_PASSWORD );
772
+ }
773
+
774
+ // Set the host
775
+ $cmd .= ' -h ' . escapeshellarg( $host );
776
+
777
+ // Set the port if it was set
778
+ if ( ! empty( $port ) && is_numeric( $port ) ) {
779
+ $cmd .= ' -P ' . $port;
780
+ }
781
+
782
+ // The file we're saving too
783
+ $cmd .= ' -r ' . escapeshellarg( $this->get_database_dump_filepath() );
784
+
785
+ // The database we're dumping
786
+ $cmd .= ' ' . escapeshellarg( DB_NAME );
787
+
788
+ // Pipe STDERR to STDOUT
789
+ $cmd .= ' 2>&1';
790
+
791
+ // Store any returned data in an error
792
+ $stderr = shell_exec( $cmd );
793
+
794
+ // Skip the new password warning that is output in mysql > 5.6 (@see http://bugs.mysql.com/bug.php?id=66546)
795
+ if ( trim( $stderr ) === 'Warning: Using a password on the command line interface can be insecure.' ) {
796
+ $stderr = '';
797
+ }
798
+
799
+ if ( $stderr ) {
800
+ $this->error( $this->get_mysqldump_method(), $stderr );
801
+ }
802
+
803
+ $this->verify_mysqldump();
804
+
805
+ }
806
+
807
+ /**
808
+ * PHP mysqldump fallback functions, exports the database to a .sql file
809
+ *
810
+ */
811
+ public function mysqldump_fallback() {
812
+
813
+ $this->errors_to_warnings( $this->get_mysqldump_method() );
814
+
815
+ $this->mysqldump_method = 'mysqldump_fallback';
816
+
817
+ $this->do_action( 'hmbkp_mysqldump_started' );
818
+
819
+ $this->db = @mysql_pconnect( DB_HOST, DB_USER, DB_PASSWORD );
820
+
821
+ if ( ! $this->db ) {
822
+ $this->db = mysql_connect( DB_HOST, DB_USER, DB_PASSWORD );
823
+ }
824
+
825
+ if ( ! $this->db ) {
826
+ return;
827
+ }
828
+
829
+ mysql_select_db( DB_NAME, $this->db );
830
+
831
+ if ( function_exists( 'mysql_set_charset' ) ) {
832
+ mysql_set_charset( DB_CHARSET, $this->db );
833
+ }
834
+
835
+ // Begin new backup of MySql
836
+ $tables = mysql_query( 'SHOW TABLES' );
837
+
838
+ $sql_file = "# WordPress : " . get_bloginfo( 'url' ) . " MySQL database backup\n";
839
+ $sql_file .= "#\n";
840
+ $sql_file .= "# Generated: " . date( 'l j. F Y H:i T' ) . "\n";
841
+ $sql_file .= "# Hostname: " . DB_HOST . "\n";
842
+ $sql_file .= "# Database: " . $this->sql_backquote( DB_NAME ) . "\n";
843
+ $sql_file .= "# --------------------------------------------------------\n";
844
+
845
+ for ( $i = 0; $i < mysql_num_rows( $tables ); $i ++ ) {
846
+
847
+ $curr_table = mysql_tablename( $tables, $i );
848
+
849
+ // Create the SQL statements
850
+ $sql_file .= "# --------------------------------------------------------\n";
851
+ $sql_file .= "# Table: " . $this->sql_backquote( $curr_table ) . "\n";
852
+ $sql_file .= "# --------------------------------------------------------\n";
853
+
854
+ $this->make_sql( $sql_file, $curr_table );
855
+
856
+ }
857
+
858
+ }
859
+
860
+ /**
861
+ * Zip up all the files.
862
+ *
863
+ * Attempts to use the shell zip command, if
864
+ * thats not available then it falls back to
865
+ * PHP ZipArchive and finally PclZip.
866
+ *
867
+ */
868
+ public function archive() {
869
+
870
+ // Do we have the path to the zip command
871
+ if ( $this->get_zip_command_path() ) {
872
+ $this->zip();
873
+ }
874
+
875
+ // If not or if the shell zip failed then use ZipArchive
876
+ if ( empty( $this->archive_verified ) && class_exists( 'ZipArchive' ) && empty( $this->skip_zip_archive ) ) {
877
+ $this->zip_archive();
878
+ }
879
+
880
+ // If ZipArchive is unavailable or one of the above failed
881
+ if ( empty( $this->archive_verified ) ) {
882
+ $this->pcl_zip();
883
+ }
884
+
885
+ // Delete the database dump file
886
+ if ( file_exists( $this->get_database_dump_filepath() ) ) {
887
+ unlink( $this->get_database_dump_filepath() );
888
+ }
889
+
890
+ $this->do_action( 'hmbkp_archive_finished' );
891
+
892
+ }
893
+
894
+ /**
895
+ * Zip using the native zip command
896
+ */
897
+ public function zip() {
898
+
899
+ // If we have an existing archive let's duplicate it so we can just add changed files to save time
900
+ if ( $this->get_existing_archive_filepath() ) {
901
+ copy( $this->get_existing_archive_filepath(), $this->get_archive_filepath() );
902
+ }
903
+
904
+ $this->archive_method = 'zip';
905
+
906
+ $this->do_action( 'hmbkp_archive_started' );
907
+
908
+ // Zip up $this->root
909
+ if ( $this->get_type() !== 'database' ) {
910
+
911
+ // cd to the site root
912
+ $command = 'cd ' . escapeshellarg( $this->get_root() );
913
+
914
+ // Run the zip command with the recursive and quiet flags
915
+ $command .= ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -rq ';
916
+
917
+ // If the destination zip file already exists then let's just add changed files to save time
918
+ if ( file_exists( $this->get_archive_filepath() ) && $this->get_existing_archive_filepath() ) {
919
+ $command .= ' -FS ';
920
+ }
921
+
922
+ // Save the zip file to the correct path
923
+ $command .= escapeshellarg( $this->get_archive_filepath() ) . ' ./';
924
+
925
+ // Pass exclude rules in if we have them
926
+ if ( $this->exclude_string( 'zip' ) ) {
927
+ $command .= ' -x ' . $this->exclude_string( 'zip' );
928
+ }
929
+
930
+ // Push all output to STDERR
931
+ $command .= ' 2>&1';
932
+
933
+ $stderr = shell_exec( $command );
934
+
935
+ }
936
+
937
+ // Add the database dump to the archive
938
+ if ( $this->get_type() !== 'file' && file_exists( $this->get_database_dump_filepath() ) ) {
939
+ $stderr = shell_exec( 'cd ' . escapeshellarg( $this->get_path() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -q ' . escapeshellarg( $this->get_archive_filepath() ) . ' ' . escapeshellarg( $this->get_database_dump_filename() ) . ' 2>&1' );
940
+ }
941
+
942
+ if ( ! empty( $stderr ) ) {
943
+ $this->warning( $this->get_archive_method(), $stderr );
944
+ }
945
+
946
+ $this->verify_archive();
947
+
948
+ }
949
+
950
+ /**
951
+ * Fallback for creating zip archives if zip command is
952
+ * unavailable.
953
+ */
954
+ public function zip_archive() {
955
+
956
+ $this->errors_to_warnings( $this->get_archive_method() );
957
+ $this->archive_method = 'ziparchive';
958
+
959
+ $this->do_action( 'hmbkp_archive_started' );
960
+
961
+ $zip = new \ZipArchive();
962
+
963
+ if ( ! class_exists( 'ZipArchive' ) || ! $zip->open( $this->get_archive_filepath(), \ZIPARCHIVE::CREATE ) ) {
964
+ return;
965
+ }
966
+
967
+ $excludes = $this->exclude_string( 'regex' );
968
+
969
+ // Add the database
970
+ if ( $this->get_type() !== 'file' && file_exists( $this->get_database_dump_filepath() ) ) {
971
+ $zip->addFile( $this->get_database_dump_filepath(), $this->get_database_dump_filename() );
972
+ }
973
+
974
+ if ( $this->get_type() !== 'database' ) {
975
+
976
+ $files_added = 0;
977
+
978
+ foreach ( $this->get_files() as $file ) {
979
+
980
+ // Skip dot files, they should only exist on versions of PHP between 5.2.11 -> 5.3
981
+ if ( method_exists( $file, 'isDot' ) && $file->isDot() ) {
982
+ continue;
983
+ }
984
+
985
+ // Skip unreadable files
986
+ if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) {
987
+ continue;
988
+ }
989
+
990
+ // Excludes
991
+ if ( $excludes && preg_match( '(' . $excludes . ')', str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) ) ) {
992
+ continue;
993
+ }
994
+
995
+ if ( $file->isDir() ) {
996
+ $zip->addEmptyDir( trailingslashit( str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) ) );
997
+ }
998
+
999
+ elseif ( $file->isFile() ) {
1000
+ $zip->addFile( $file->getPathname(), str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) );
1001
+ }
1002
+
1003
+ if ( ++$files_added % 500 === 0 ) {
1004
+ if ( ! $zip->close() || ! $zip->open( $this->get_archive_filepath(), \ZIPARCHIVE::CREATE ) ) {
1005
+ return;
1006
+ }
1007
+ }
1008
+
1009
+ }
1010
+
1011
+ }
1012
+
1013
+ if ( $zip->status ) {
1014
+ $this->warning( $this->get_archive_method(), $zip->status );
1015
+ }
1016
+
1017
+ if ( $zip->statusSys ) {
1018
+ $this->warning( $this->get_archive_method(), $zip->statusSys );
1019
+ }
1020
+
1021
+ $zip->close();
1022
+
1023
+ $this->verify_archive();
1024
+
1025
+ }
1026
+
1027
+ /**
1028
+ * Fallback for creating zip archives if zip command and ZipArchive are
1029
+ * unavailable.
1030
+ *
1031
+ * Uses the PclZip library that ships with WordPress
1032
+ */
1033
+ public function pcl_zip() {
1034
+
1035
+ $this->errors_to_warnings( $this->get_archive_method() );
1036
+ $this->archive_method = 'pclzip';
1037
+
1038
+ $this->do_action( 'hmbkp_archive_started' );
1039
+
1040
+ global $_hmbkp_exclude_string;
1041
+
1042
+ $_hmbkp_exclude_string = $this->exclude_string( 'regex' );
1043
+
1044
+ $this->load_pclzip();
1045
+
1046
+ $archive = new \PclZip( $this->get_archive_filepath() );
1047
+
1048
+ // Add the database
1049
+ if ( $this->get_type() !== 'file' && file_exists( $this->get_database_dump_filepath() ) ) {
1050
+ if ( ! $archive->add( $this->get_database_dump_filepath(), \PCLZIP_OPT_REMOVE_PATH, $this->get_path() ) ) {
1051
+ $this->warning( $this->get_archive_method(), $archive->errorInfo( true ) );
1052
+ }
1053
+ }
1054
+
1055
+ // Zip up everything
1056
+ if ( $this->get_type() !== 'database' ) {
1057
+ if ( ! $archive->add( $this->get_root(), \PCLZIP_OPT_REMOVE_PATH, $this->get_root(), \PCLZIP_CB_PRE_ADD, 'hmbkp_pclzip_callback' ) ) {
1058
+ $this->warning( $this->get_archive_method(), $archive->errorInfo( true ) );
1059
+ }
1060
+ }
1061
+
1062
+ unset( $GLOBALS['_hmbkp_exclude_string'] );
1063
+
1064
+ $this->verify_archive();
1065
+
1066
+ }
1067
+
1068
+ public function verify_mysqldump() {
1069
+
1070
+ $this->do_action( 'hmbkp_mysqldump_verify_started' );
1071
+
1072
+ // If we've already passed then no need to check again
1073
+ if ( ! empty( $this->mysqldump_verified ) ) {
1074
+ return true;
1075
+ }
1076
+
1077
+ // If there are mysqldump errors delete the database dump file as mysqldump will still have written one
1078
+ if ( $this->get_errors( $this->get_mysqldump_method() ) && file_exists( $this->get_database_dump_filepath() ) ) {
1079
+ unlink( $this->get_database_dump_filepath() );
1080
+ }
1081
+
1082
+ // If we have an empty file delete it
1083
+ if ( @filesize( $this->get_database_dump_filepath() ) === 0 ) {
1084
+ unlink( $this->get_database_dump_filepath() );
1085
+ }
1086
+
1087
+ // If the file still exists then it must be good
1088
+ if ( file_exists( $this->get_database_dump_filepath() ) ) {
1089
+ return $this->mysqldump_verified = true;
1090
+ }
1091
+
1092
+ return false;
1093
+
1094
+
1095
+ }
1096
+
1097
+ /**
1098
+ * Verify that the archive is valid and contains all the files it should contain.
1099
+ *
1100
+ * @return bool
1101
+ */
1102
+ public function verify_archive() {
1103
+
1104
+ $this->do_action( 'hmbkp_archive_verify_started' );
1105
+
1106
+ // If we've already passed then no need to check again
1107
+ if ( ! empty( $this->archive_verified ) ) {
1108
+ return true;
1109
+ }
1110
+
1111
+ // If there are errors delete the backup file.
1112
+ if ( $this->get_errors( $this->get_archive_method() ) && file_exists( $this->get_archive_filepath() ) ) {
1113
+ unlink( $this->get_archive_filepath() );
1114
+ }
1115
+
1116
+ // If the archive file still exists assume it's good
1117
+ if ( file_exists( $this->get_archive_filepath() ) ) {
1118
+ return $this->archive_verified = true;
1119
+ }
1120
+
1121
+ return false;
1122
+
1123
+ }
1124
+
1125
+ /**
1126
+ * Return an array of all files in the filesystem
1127
+ *
1128
+ * @return \RecursiveIteratorIterator
1129
+ */
1130
+ public function get_files() {
1131
+
1132
+ if ( ! empty( $this->files ) ) {
1133
+ return $this->files;
1134
+ }
1135
+
1136
+ $this->files = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $this->get_root(), \RecursiveDirectoryIterator::SKIP_DOTS + \RecursiveDirectoryIterator::FOLLOW_SYMLINKS ), \RecursiveIteratorIterator::SELF_FIRST, \RecursiveIteratorIterator::CATCH_GET_CHILD );
1137
+
1138
+ return $this->files;
1139
+
1140
+ }
1141
+
1142
+ /**
1143
+ * Returns an array of files that will be included in the backup.
1144
+ *
1145
+ * @return array
1146
+ */
1147
+ public function get_included_files() {
1148
+
1149
+ if ( ! empty( $this->included_files ) ) {
1150
+ return $this->included_files;
1151
+ }
1152
+
1153
+ $this->included_files = array();
1154
+
1155
+ $excludes = $this->exclude_string( 'regex' );
1156
+
1157
+ foreach ( $this->get_files() as $file ) {
1158
+
1159
+ // Skip dot files, they should only exist on versions of PHP between 5.2.11 -> 5.3
1160
+ if ( method_exists( $file, 'isDot' ) && $file->isDot() ) {
1161
+ continue;
1162
+ }
1163
+
1164
+ // Skip unreadable files
1165
+ if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) {
1166
+ continue;
1167
+ }
1168
+
1169
+ // Excludes
1170
+ if ( $excludes && preg_match( '(' . $excludes . ')', str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) ) ) {
1171
+ continue;
1172
+ }
1173
+
1174
+ $this->included_files[] = $file;
1175
+
1176
+ }
1177
+
1178
+ return $this->included_files;
1179
+
1180
+ }
1181
+
1182
+ /**
1183
+ * Returns an array of files that match the exclude rules.
1184
+ *
1185
+ * @return array
1186
+ */
1187
+ public function get_excluded_files() {
1188
+
1189
+ if ( ! empty( $this->excluded_files ) ) {
1190
+ return $this->excluded_files;
1191
+ }
1192
+
1193
+ $this->excluded_files = array();
1194
+
1195
+ $excludes = $this->exclude_string( 'regex' );
1196
+
1197
+ foreach ( $this->get_files() as $file ) {
1198
+
1199
+ // Skip dot files, they should only exist on versions of PHP between 5.2.11 -> 5.3
1200
+ if ( method_exists( $file, 'isDot' ) && $file->isDot() ) {
1201
+ continue;
1202
+ }
1203
+
1204
+ // Skip unreadable files
1205
+ if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) {
1206
+ continue;
1207
+ }
1208
+
1209
+ // Excludes
1210
+ if ( $excludes && preg_match( '(' . $excludes . ')', str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) ) ) {
1211
+ $this->excluded_files[] = $file;
1212
+ }
1213
+
1214
+ }
1215
+
1216
+ return $this->excluded_files;
1217
+
1218
+ }
1219
+
1220
+ /**
1221
+ * Returns an array of unreadable files.
1222
+ *
1223
+ * @return array
1224
+ */
1225
+ public function get_unreadable_files() {
1226
+
1227
+ if ( ! empty( $this->unreadable_files ) ) {
1228
+ return $this->unreadable_files;
1229
+ }
1230
+
1231
+ $this->unreadable_files = array();
1232
+
1233
+ foreach ( $this->get_files() as $file ) {
1234
+
1235
+ // Skip dot files, they should only exist on versions of PHP between 5.2.11 -> 5.3
1236
+ if ( method_exists( $file, 'isDot' ) && $file->isDot() ) {
1237
+ continue;
1238
+ }
1239
+
1240
+ if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) {
1241
+ $this->unreadable_files[] = $file;
1242
+ }
1243
+
1244
+ }
1245
+
1246
+ return $this->unreadable_files;
1247
+
1248
+ }
1249
+
1250
+ private function load_pclzip() {
1251
+
1252
+ // Load PclZip
1253
+ if ( ! defined( 'PCLZIP_TEMPORARY_DIR' ) ) {
1254
+ define( 'PCLZIP_TEMPORARY_DIR', trailingslashit( $this->get_path() ) );
1255
+ }
1256
+
1257
+ require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
1258
+
1259
+ }
1260
+
1261
+ /**
1262
+ * Get an array of exclude rules
1263
+ *
1264
+ * The backup path is automatically excluded
1265
+ *
1266
+ * @return array
1267
+ */
1268
+ public function get_excludes() {
1269
+
1270
+ $excludes = array();
1271
+
1272
+ if ( isset( $this->excludes ) ) {
1273
+ $excludes = $this->excludes;
1274
+ }
1275
+
1276
+ // If path() is inside root(), exclude it
1277
+ if ( strpos( $this->get_path(), $this->get_root() ) !== false ) {
1278
+ array_unshift( $excludes, trailingslashit( $this->get_path() ) );
1279
+ }
1280
+
1281
+ return array_unique( $excludes );
1282
+
1283
+ }
1284
+
1285
+ /**
1286
+ * Set the excludes, expects and array
1287
+ *
1288
+ * @param Array $excludes
1289
+ * @param Bool $append
1290
+ */
1291
+ public function set_excludes( $excludes, $append = false ) {
1292
+
1293
+ if ( is_string( $excludes ) ) {
1294
+ $excludes = explode( ',', $excludes );
1295
+ }
1296
+
1297
+ if ( $append ) {
1298
+ $excludes = array_merge( $this->excludes, $excludes );
1299
+ }
1300
+
1301
+ $this->excludes = array_filter( array_unique( array_map( 'trim', $excludes ) ) );
1302
+
1303
+ }
1304
+
1305
+ /**
1306
+ * Generate the exclude param string for the zip backup
1307
+ *
1308
+ * Takes the exclude rules and formats them for use with either
1309
+ * the shell zip command or pclzip
1310
+ *
1311
+ * @param string $context. (default: 'zip')
1312
+ * @return string
1313
+ */
1314
+ public function exclude_string( $context = 'zip' ) {
1315
+
1316
+ // Return a comma separated list by default
1317
+ $separator = ', ';
1318
+ $wildcard = '';
1319
+
1320
+ // The zip command
1321
+ if ( $context === 'zip' ) {
1322
+ $wildcard = '*';
1323
+ $separator = ' -x ';
1324
+
1325
+ // The PclZip fallback library
1326
+ }
1327
+ elseif ( $context === 'regex' ) {
1328
+ $wildcard = '([\s\S]*?)';
1329
+ $separator = '|';
1330
+ }
1331
+
1332
+ $excludes = $this->get_excludes();
1333
+
1334
+ foreach ( $excludes as $key => &$rule ) {
1335
+
1336
+ $file = $absolute = $fragment = false;
1337
+
1338
+ // Files don't end with /
1339
+ if ( ! in_array( substr( $rule, - 1 ), array( '\\', '/' ) ) ) {
1340
+ $file = true;
1341
+ }
1342
+
1343
+ // If rule starts with a / then treat as absolute path
1344
+ elseif ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) ) {
1345
+ $absolute = true;
1346
+ }
1347
+
1348
+ // Otherwise treat as dir fragment
1349
+ else {
1350
+ $fragment = true;
1351
+ }
1352
+
1353
+ // Strip $this->root and conform
1354
+ $rule = str_ireplace( $this->get_root(), '', untrailingslashit( self::conform_dir( $rule ) ) );
1355
+
1356
+
1357
+ // Strip the preceeding slash
1358
+ if ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) ) {
1359
+ $rule = substr( $rule, 1 );
1360
+ }
1361
+
1362
+ // Escape string for regex
1363
+ if ( $context === 'regex' ) {
1364
+ $rule = str_replace( '.', '\.', $rule );
1365
+ }
1366
+
1367
+ // Convert any existing wildcards
1368
+ if ( $wildcard !== '*' && false !== strpos( $rule, '*' ) ) {
1369
+ $rule = str_replace( '*', $wildcard, $rule );
1370
+ }
1371
+
1372
+ // Wrap directory fragments and files in wildcards for zip
1373
+ if ( 'zip' === $context && ( $fragment || $file ) ) {
1374
+ $rule = $wildcard . $rule . $wildcard;
1375
+ }
1376
+
1377
+ // Add a wildcard to the end of absolute url for zips
1378
+ if ( 'zip' === $context && $absolute ) {
1379
+ $rule .= $wildcard;
1380
+ }
1381
+
1382
+ // Add and end carrot to files for pclzip but only if it doesn't end in a wildcard
1383
+ if ( $file && 'regex' === $context ) {
1384
+ $rule .= '$';
1385
+ }
1386
+
1387
+ // Add a start carrot to absolute urls for pclzip
1388
+ if ( $absolute && 'regex' === $context ) {
1389
+ $rule = '^' . $rule;
1390
+ }
1391
+
1392
+
1393
+ }
1394
+
1395
+ // Escape shell args for zip command
1396
+ if ( $context === 'zip' ) {
1397
+ $excludes = array_map( 'escapeshellarg', array_unique( $excludes ) );
1398
+ }
1399
+
1400
+ return implode( $separator, $excludes );
1401
+
1402
+ }
1403
+
1404
+ /**
1405
+ * Add backquotes to tables and db-names in SQL queries. Taken from phpMyAdmin.
1406
+ *
1407
+ * @param mixed $a_name
1408
+ * @return array|string
1409
+ */
1410
+ private function sql_backquote( $a_name ) {
1411
+
1412
+ if ( ! empty( $a_name ) && $a_name !== '*' ) {
1413
+
1414
+ if ( is_array( $a_name ) ) {
1415
+
1416
+ $result = array();
1417
+
1418
+ reset( $a_name );
1419
+
1420
+ while ( list( $key, $val ) = each( $a_name ) ) {
1421
+ $result[$key] = '`' . $val . '`';
1422
+ }
1423
+
1424
+ return $result;
1425
+
1426
+ } else {
1427
+ return '`' . $a_name . '`';
1428
+ }
1429
+
1430
+ } else {
1431
+ return $a_name;
1432
+ }
1433
+
1434
+ }
1435
+
1436
+ /**
1437
+ * Reads the Database table in $table and creates
1438
+ * SQL Statements for recreating structure and data
1439
+ * Taken partially from phpMyAdmin and partially from
1440
+ * Alain Wolf, Zurich - Switzerland
1441
+ * Website: http://restkultur.ch/personal/wolf/scripts/db_backup/
1442
+ *
1443
+ * @param string $sql_file
1444
+ * @param string $table
1445
+ */
1446
+ private function make_sql( $sql_file, $table ) {
1447
+
1448
+ // Add SQL statement to drop existing table
1449
+ $sql_file .= "\n";
1450
+ $sql_file .= "\n";
1451
+ $sql_file .= "#\n";
1452
+ $sql_file .= "# Delete any existing table " . $this->sql_backquote( $table ) . "\n";
1453
+ $sql_file .= "#\n";
1454
+ $sql_file .= "\n";
1455
+ $sql_file .= "DROP TABLE IF EXISTS " . $this->sql_backquote( $table ) . ";\n";
1456
+
1457
+ /* Table Structure */
1458
+
1459
+ // Comment in SQL-file
1460
+ $sql_file .= "\n";
1461
+ $sql_file .= "\n";
1462
+ $sql_file .= "#\n";
1463
+ $sql_file .= "# Table structure of table " . $this->sql_backquote( $table ) . "\n";
1464
+ $sql_file .= "#\n";
1465
+ $sql_file .= "\n";
1466
+
1467
+ // Get table structure
1468
+ $query = 'SHOW CREATE TABLE ' . $this->sql_backquote( $table );
1469
+ $result = mysql_query( $query, $this->db );
1470
+
1471
+ if ( $result ) {
1472
+
1473
+ if ( mysql_num_rows( $result ) > 0 ) {
1474
+ $sql_create_arr = mysql_fetch_array( $result );
1475
+ $sql_file .= $sql_create_arr[1];
1476
+ }
1477
+
1478
+ mysql_free_result( $result );
1479
+ $sql_file .= ' ;';
1480
+
1481
+ }
1482
+
1483
+ /* Table Contents */
1484
+
1485
+ // Get table contents
1486
+ $query = 'SELECT * FROM ' . $this->sql_backquote( $table );
1487
+ $result = mysql_query( $query, $this->db );
1488
+
1489
+ $fields_cnt = 0;
1490
+ $rows_cnt = 0;
1491
+
1492
+ if ( $result ) {
1493
+ $fields_cnt = mysql_num_fields( $result );
1494
+ $rows_cnt = mysql_num_rows( $result );
1495
+ }
1496
+
1497
+ // Comment in SQL-file
1498
+ $sql_file .= "\n";
1499
+ $sql_file .= "\n";
1500
+ $sql_file .= "#\n";
1501
+ $sql_file .= "# Data contents of table " . $table . " (" . $rows_cnt . " records)\n";
1502
+ $sql_file .= "#\n";
1503
+
1504
+ $field_set = $field_num = array();
1505
+
1506
+ // Checks whether the field is an integer or not
1507
+ for ( $j = 0; $j < $fields_cnt; $j ++ ) {
1508
+
1509
+ $field_set[$j] = $this->sql_backquote( mysql_field_name( $result, $j ) );
1510
+ $type = mysql_field_type( $result, $j );
1511
+
1512
+ if ( $type === 'tinyint' || $type === 'smallint' || $type === 'mediumint' || $type === 'int' || $type === 'bigint' ) {
1513
+ $field_num[$j] = true;
1514
+ } else {
1515
+ $field_num[$j] = false;
1516
+ }
1517
+
1518
+ }
1519
+
1520
+ // Sets the scheme
1521
+ $entries = 'INSERT INTO ' . $this->sql_backquote( $table ) . ' VALUES (';
1522
+ $search = array( '\x00', '\x0a', '\x0d', '\x1a' ); //\x08\\x09, not required
1523
+ $replace = array( '\0', '\n', '\r', '\Z' );
1524
+ $current_row = 0;
1525
+ $batch_write = 0;
1526
+
1527
+ $values = array();
1528
+
1529
+ while ( $row = mysql_fetch_row( $result ) ) {
1530
+
1531
+ $current_row ++;
1532
+
1533
+ // build the statement
1534
+ for ( $j = 0; $j < $fields_cnt; $j ++ ) {
1535
+
1536
+ if ( ! isset( $row[$j] ) ) {
1537
+ $values[] = 'NULL';
1538
+
1539
+ }
1540
+ elseif ( $row[$j] === '0' || $row[$j] !== '' ) {
1541
+
1542
+ // a number
1543
+ if ( $field_num[$j] ) {
1544
+ $values[] = $row[$j];
1545
+ } else {
1546
+ $values[] = "'" . str_replace( $search, $replace, $this->sql_addslashes( $row[$j] ) ) . "'";
1547
+ }
1548
+
1549
+ } else {
1550
+ $values[] = "''";
1551
+ }
1552
+
1553
+ }
1554
+
1555
+ $sql_file .= " \n" . $entries . implode( ', ', $values ) . ") ;";
1556
+
1557
+ // write the rows in batches of 100
1558
+ if ( $batch_write === 100 ) {
1559
+ $batch_write = 0;
1560
+ $this->write_sql( $sql_file );
1561
+ $sql_file = '';
1562
+ }
1563
+
1564
+ $batch_write ++;
1565
+
1566
+ unset( $values );
1567
+
1568
+ }
1569
+
1570
+ mysql_free_result( $result );
1571
+
1572
+ // Create footer/closing comment in SQL-file
1573
+ $sql_file .= "\n";
1574
+ $sql_file .= "#\n";
1575
+ $sql_file .= "# End of data contents of table " . $table . "\n";
1576
+ $sql_file .= "# --------------------------------------------------------\n";
1577
+ $sql_file .= "\n";
1578
+
1579
+ $this->write_sql( $sql_file );
1580
+
1581
+ }
1582
+
1583
+ /**
1584
+ * Better addslashes for SQL queries.
1585
+ * Taken from phpMyAdmin.
1586
+ *
1587
+ * @param string $a_string (default: '')
1588
+ * @param bool $is_like (default: false)
1589
+ * @return mixed
1590
+ */
1591
+ private function sql_addslashes( $a_string = '', $is_like = false ) {
1592
+
1593
+ if ( $is_like ) {
1594
+ $a_string = str_replace( '\\', '\\\\\\\\', $a_string );
1595
+ } else {
1596
+ $a_string = str_replace( '\\', '\\\\', $a_string );
1597
+ }
1598
+
1599
+ $a_string = str_replace( '\'', '\\\'', $a_string );
1600
+
1601
+ return $a_string;
1602
+ }
1603
+
1604
+ /**
1605
+ * Write the SQL file
1606
+ *
1607
+ * @param string $sql
1608
+ * @return null|boolean
1609
+ */
1610
+ private function write_sql( $sql ) {
1611
+
1612
+ $sqlname = $this->get_database_dump_filepath();
1613
+
1614
+ // Actually write the sql file
1615
+ if ( is_writable( $sqlname ) || ! file_exists( $sqlname ) ) {
1616
+
1617
+ if ( ! $handle = @fopen( $sqlname, 'a' ) ) {
1618
+ return;
1619
+ }
1620
+
1621
+ if ( ! fwrite( $handle, $sql ) ) {
1622
+ return;
1623
+ }
1624
+
1625
+ fclose( $handle );
1626
+
1627
+ return true;
1628
+
1629
+ }
1630
+
1631
+ }
1632
+
1633
+ /**
1634
+ * Get the errors
1635
+ *
1636
+ */
1637
+ public function get_errors( $context = null ) {
1638
+
1639
+ if ( ! empty( $context ) ) {
1640
+ return isset( $this->errors[$context] ) ? $this->errors[$context] : array();
1641
+ }
1642
+
1643
+ return $this->errors;
1644
+
1645
+ }
1646
+
1647
+ /**
1648
+ * Add an error to the errors stack
1649
+ *
1650
+ * @param string $context
1651
+ * @param mixed $error
1652
+ */
1653
+ public function error( $context, $error ) {
1654
+
1655
+ if ( empty( $context ) || empty( $error ) ) {
1656
+ return;
1657
+ }
1658
+
1659
+ $this->do_action( 'hmbkp_error' );
1660
+
1661
+ $this->errors[$context][$_key = md5( implode( ':', (array) $error ) )] = $error;
1662
+
1663
+ }
1664
+
1665
+ /**
1666
+ * Migrate errors to warnings
1667
+ *
1668
+ * @param null $context
1669
+ */
1670
+ private function errors_to_warnings( $context = null ) {
1671
+
1672
+ $errors = empty( $context ) ? $this->get_errors() : array( $context => $this->get_errors( $context ) );
1673
+
1674
+ if ( empty( $errors ) ) {
1675
+ return;
1676
+ }
1677
+
1678
+ foreach ( $errors as $error_context => $context_errors ) {
1679
+ foreach ( $context_errors as $error ) {
1680
+ $this->warning( $error_context, $error );
1681
+ }
1682
+ }
1683
+
1684
+ if ( $context ) {
1685
+ unset( $this->errors[$context] );
1686
+ }
1687
+
1688
+ else {
1689
+ $this->errors = array();
1690
+ }
1691
+
1692
+ }
1693
+
1694
+ /**
1695
+ * Get the warnings
1696
+ *
1697
+ */
1698
+ public function get_warnings( $context = null ) {
1699
+
1700
+ if ( ! empty( $context ) ) {
1701
+ return isset( $this->warnings[$context] ) ? $this->warnings[$context] : array();
1702
+ }
1703
+
1704
+ return $this->warnings;
1705
+
1706
+ }
1707
+
1708
+ /**
1709
+ * Add an warning to the warnings stack
1710
+ *
1711
+ * @param string $context
1712
+ * @param mixed $warning
1713
+ */
1714
+ private function warning( $context, $warning ) {
1715
+
1716
+ if ( empty( $context ) || empty( $warning ) ) {
1717
+ return;
1718
+ }
1719
+
1720
+ $this->do_action( 'hmbkp_warning' );
1721
+
1722
+ $this->warnings[$context][$_key = md5( implode( ':', (array) $warning ) )] = $warning;
1723
+
1724
+ }
1725
+
1726
+ /**
1727
+ * Custom error handler for catching php errors
1728
+ *
1729
+ * @param $type
1730
+ * @return bool
1731
+ */
1732
+ public function error_handler( $type ) {
1733
+
1734
+ // Skip strict & deprecated warnings
1735
+ if ( ( defined( 'E_DEPRECATED' ) && $type === E_DEPRECATED ) || ( defined( 'E_STRICT' ) && $type === E_STRICT ) || error_reporting() === 0 ) {
1736
+ return false;
1737
+ }
1738
+
1739
+ $args = func_get_args();
1740
+
1741
+ array_shift( $args );
1742
+
1743
+ $this->warning( 'php', implode( ', ', array_splice( $args, 0, 3 ) ) );
1744
+
1745
+ return false;
1746
+
1747
+ }
1748
+
1749
+ }
1750
+
1751
+ }
1752
+
1753
+ // We need this function to exist in the global namespace
1754
+ // TODO obviously this should be fixed at some point
1755
+ namespace {
1756
+
1757
+ /**
1758
+ * Add file callback for PclZip, excludes files
1759
+ * and sets the database dump to be stored in the root
1760
+ * of the zip
1761
+ *
1762
+ * @param string $event
1763
+ * @param array $file
1764
+ * @return bool
1765
+ */
1766
+ function hmbkp_pclzip_callback( $event, $file ) {
1767
+
1768
+ global $_hmbkp_exclude_string;
1769
+
1770
+ // Don't try to add unreadable files.
1771
+ if ( ! is_readable( $file['filename'] ) || ! file_exists( $file['filename'] ) ) {
1772
+ return false;
1773
+ }
1774
+
1775
+ // Match everything else past the exclude list
1776
+ elseif ( $_hmbkp_exclude_string && preg_match( '(' . $_hmbkp_exclude_string . ')', $file['stored_filename'] ) ) {
1777
+ return false;
1778
+ }
1779
+
1780
+ return true;
1781
+
1782
+ }
1783
+
1784
+ }
classes/{wp-cli.php → class-backupwordpress-wp-cli-command.php} RENAMED
@@ -7,7 +7,7 @@
7
  * @package wp-cli
8
  * @subpackage commands/third-party
9
  */
10
- class BackUpCommand extends WP_CLI_Command {
11
 
12
  /**
13
  * Perform a Backup.
@@ -20,7 +20,7 @@ class BackUpCommand extends WP_CLI_Command {
20
  * [--database_only]
21
  * : Backup database only, defaults to off
22
  *
23
- * [--path]
24
  * : dir that the backup should be save in, defaults to your existing backups directory
25
  *
26
  * [--root]
@@ -32,10 +32,17 @@ class BackUpCommand extends WP_CLI_Command {
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
  */
40
  public function backup( $args, $assoc_args ) {
41
 
@@ -47,32 +54,32 @@ class BackUpCommand extends WP_CLI_Command {
47
  WP_CLI::line( __( 'Backup: Zipping everything up...', 'backupwordpress' ) );
48
  } );
49
 
50
- $hm_backup = new HM_Backup();
51
 
52
- if ( ! empty( $assoc_args['path'] ) ) {
53
- HMBKP_Path::get_instance()->set_path( $assoc_args['path'] );
54
  }
55
 
56
- $hm_backup->set_path( HMBKP_Path::get_instance()->get_path() );
57
-
58
- HMBKP_Path::get_instance()->cleanup();
59
 
60
  if ( ! empty( $assoc_args['root'] ) ) {
61
  $hm_backup->set_root( $assoc_args['root'] );
62
  }
63
 
64
- if ( ( ! is_dir( $hm_backup->get_path() ) && ( ! is_writable( dirname( $hm_backup->get_path() ) ) || ! wp_mkdir_p( $hm_backup->get_path() ) ) ) || ! is_writable( $hm_backup->get_path() ) ) {
65
  WP_CLI::error( __( 'Invalid backup path', 'backupwordpress' ) );
66
-
67
  return false;
68
  }
69
 
70
  if ( ! is_dir( $hm_backup->get_root() ) || ! is_readable( $hm_backup->get_root() ) ) {
71
  WP_CLI::error( __( 'Invalid root path', 'backupwordpress' ) );
72
-
73
  return false;
74
  }
75
 
 
 
 
 
76
  if ( ! empty( $assoc_args['files_only'] ) ) {
77
  $hm_backup->set_type( 'file' );
78
  }
7
  * @package wp-cli
8
  * @subpackage commands/third-party
9
  */
10
+ class BackUpWordPress_WP_CLI_Command extends WP_CLI_Command {
11
 
12
  /**
13
  * Perform a Backup.
20
  * [--database_only]
21
  * : Backup database only, defaults to off
22
  *
23
+ * [--destination]
24
  * : dir that the backup should be save in, defaults to your existing backups directory
25
  *
26
  * [--root]
32
  * [--mysqldump_command_path]
33
  * : path to your mysqldump binary, standard locations are automatically used
34
  *
35
+ * [--archive_filename]
36
+ * : filename for the resulting zip file
37
+ *
38
+ * [--excludes]
39
+ * : list of paths you'd like to exclude
40
+ *
41
  * ## Usage
42
  *
43
  * wp backupwordpress backup [--files_only] [--database_only] [--path<dir>] [--root<dir>] [--zip_command_path=<path>] [--mysqldump_command_path=<path>]
44
  *
45
+ * @todo errors should be bubbled from Backup, Scheduled_Backup and the like instead of being repeated.
46
  */
47
  public function backup( $args, $assoc_args ) {
48
 
54
  WP_CLI::line( __( 'Backup: Zipping everything up...', 'backupwordpress' ) );
55
  } );
56
 
57
+ $hm_backup = new Backup();
58
 
59
+ if ( ! empty( $assoc_args['destination'] ) ) {
60
+ Path::get_instance()->set_path( $assoc_args['destination'] );
61
  }
62
 
63
+ Path::get_instance()->cleanup();
 
 
64
 
65
  if ( ! empty( $assoc_args['root'] ) ) {
66
  $hm_backup->set_root( $assoc_args['root'] );
67
  }
68
 
69
+ if ( ( ! is_dir( hmbkp_path() ) ) ) {
70
  WP_CLI::error( __( 'Invalid backup path', 'backupwordpress' ) );
 
71
  return false;
72
  }
73
 
74
  if ( ! is_dir( $hm_backup->get_root() ) || ! is_readable( $hm_backup->get_root() ) ) {
75
  WP_CLI::error( __( 'Invalid root path', 'backupwordpress' ) );
 
76
  return false;
77
  }
78
 
79
+ if ( isset( $assoc_args['archive_filename'] ) ) {
80
+ $hm_backup->set_archive_filename( $assoc_args['archive_filename'] );
81
+ }
82
+
83
  if ( ! empty( $assoc_args['files_only'] ) ) {
84
  $hm_backup->set_type( 'file' );
85
  }
classes/{class-email.php → class-email-service.php} RENAMED
@@ -1,11 +1,13 @@
1
  <?php
2
 
 
 
3
  /**
4
  * Email notifications for backups
5
  *
6
- * @extends HMBKP_Service
7
  */
8
- class HMBKP_Email_Service extends HMBKP_Service {
9
 
10
  /**
11
  * Human readable name for this service
@@ -144,15 +146,15 @@ class HMBKP_Email_Service extends HMBKP_Service {
144
  /**
145
  * Fire the email notification on the hmbkp_backup_complete
146
  *
147
- * @see HM_Backup::do_action
148
  * @param string $action The action received from the backup
149
  * @return void
150
  */
151
- public function action( $action ) {
152
 
153
  if ( $action === 'hmbkp_backup_complete' && $this->get_email_address_array() ) {
154
 
155
- $file = $this->schedule->get_archive_filepath();
156
 
157
  $sent = false;
158
 
@@ -162,15 +164,17 @@ class HMBKP_Email_Service extends HMBKP_Service {
162
  $headers = 'From: BackUpWordPress <' . apply_filters( 'hmbkp_from_email', get_bloginfo( 'admin_email' ) ) . '>' . "\r\n";
163
 
164
  // The backup failed, send a message saying as much
165
- if ( ! file_exists( $file ) && ( $errors = array_merge( $this->schedule->get_errors(), $this->schedule->get_warnings() ) ) ) {
166
 
167
  $error_message = '';
168
 
169
- foreach ( $errors as $error_set )
170
  $error_message .= implode( "\n - ", $error_set );
 
171
 
172
- if ( $error_message )
173
  $error_message = ' - ' . $error_message;
 
174
 
175
  $subject = sprintf( __( 'Backup of %s Failed', 'backupwordpress' ), $domain );
176
 
@@ -213,4 +217,4 @@ class HMBKP_Email_Service extends HMBKP_Service {
213
  }
214
 
215
  // Register the service
216
- HMBKP_Services::register( __FILE__, 'HMBKP_Email_Service' );
1
  <?php
2
 
3
+ namespace HM\BackUpWordPress;
4
+
5
  /**
6
  * Email notifications for backups
7
  *
8
+ * @extends Service
9
  */
10
+ class Email_Service extends Service {
11
 
12
  /**
13
  * Human readable name for this service
146
  /**
147
  * Fire the email notification on the hmbkp_backup_complete
148
  *
149
+ * @see Backup::do_action
150
  * @param string $action The action received from the backup
151
  * @return void
152
  */
153
+ public function action( $action, Backup $backup ) {
154
 
155
  if ( $action === 'hmbkp_backup_complete' && $this->get_email_address_array() ) {
156
 
157
+ $file = $backup->get_archive_filepath();
158
 
159
  $sent = false;
160
 
164
  $headers = 'From: BackUpWordPress <' . apply_filters( 'hmbkp_from_email', get_bloginfo( 'admin_email' ) ) . '>' . "\r\n";
165
 
166
  // The backup failed, send a message saying as much
167
+ if ( ! file_exists( $file ) && ( $errors = array_merge( $backup->get_errors(), $backup->get_warnings() ) ) ) {
168
 
169
  $error_message = '';
170
 
171
+ foreach ( $errors as $error_set ) {
172
  $error_message .= implode( "\n - ", $error_set );
173
+ }
174
 
175
+ if ( $error_message ) {
176
  $error_message = ' - ' . $error_message;
177
+ }
178
 
179
  $subject = sprintf( __( 'Backup of %s Failed', 'backupwordpress' ), $domain );
180
 
217
  }
218
 
219
  // Register the service
220
+ Services::register( __FILE__, 'HM\BackUpWordPress\Email_Service' );
classes/class-notices.php CHANGED
@@ -1,9 +1,11 @@
1
  <?php
2
 
 
 
3
  /**
4
- * Class HMBKP_Notices
5
  */
6
- class HMBKP_Notices {
7
 
8
  /**
9
  * @var
@@ -18,12 +20,12 @@ class HMBKP_Notices {
18
  private function __construct() {}
19
 
20
  /**
21
- * @return HMBKP_Notices
22
  */
23
  public static function get_instance() {
24
 
25
- if ( ! ( self::$_instance instanceof HMBKP_Notices ) ) {
26
- self::$_instance = new HMBKP_Notices();
27
  }
28
 
29
  return self::$_instance;
1
  <?php
2
 
3
+ namespace HM\BackUpWordPress;
4
+
5
  /**
6
+ * Class Notices
7
  */
8
+ class Notices {
9
 
10
  /**
11
  * @var
20
  private function __construct() {}
21
 
22
  /**
23
+ * @return Notices
24
  */
25
  public static function get_instance() {
26
 
27
+ if ( ! ( self::$_instance instanceof Notices ) ) {
28
+ self::$_instance = new Notices();
29
  }
30
 
31
  return self::$_instance;
classes/{class-hmbkp-path.php → class-path.php} RENAMED
@@ -4,15 +4,7 @@
4
  * @subpackage BackUpWordPress/classes
5
  */
6
 
7
- /**
8
- * Returns the backup path
9
- *
10
- * @see HMBKP_Path
11
- * @todo remove the need for this
12
- */
13
- function hmbkp_path() {
14
- return HMBKP_Path::get_instance()->get_path();
15
- }
16
 
17
  /**
18
  * The Backup Path class
@@ -21,7 +13,7 @@ function hmbkp_path() {
21
  *
22
  * @todo Should be a singleton?
23
  */
24
- class HMBKP_Path {
25
 
26
  /**
27
  * The path to the directory that backup files are stored in
@@ -37,6 +29,8 @@ class HMBKP_Path {
37
  */
38
  protected $custom_path;
39
 
 
 
40
  /**
41
  * Protected constructor to prevent creating a new instance of the
42
  * *Singleton* via the `new` operator from outside of this class.
@@ -62,20 +56,17 @@ class HMBKP_Path {
62
  /**
63
  * Returns the *Singleton* instance of this class.
64
  *
65
- * @staticvar HMBKP_PAth $instance The *Singleton* instances of this class.
66
  *
67
- * @return HMBKP_Path The *Singleton* instance.
68
  */
69
  public static function get_instance() {
70
 
71
- static $instance = null;
72
-
73
- if ( null === $instance ) {
74
- $instance = new static();
75
  }
76
 
77
- return $instance;
78
-
79
  }
80
 
81
  /**
@@ -91,7 +82,7 @@ class HMBKP_Path {
91
  // Ensure the backup directory is protected
92
  $this->protect_path();
93
 
94
- return $this->path;
95
 
96
  }
97
 
@@ -109,6 +100,10 @@ class HMBKP_Path {
109
 
110
  }
111
 
 
 
 
 
112
  /**
113
  * Get the path to the default backup location in wp-content
114
  */
@@ -340,21 +335,24 @@ class HMBKP_Path {
340
  return;
341
  }
342
 
343
- if ( $handle = opendir( $this->get_path() ) ) {
344
 
345
- while ( false !== ( $file = readdir( $handle ) ) ) {
346
-
347
- if ( ! in_array( $file, array( '.', '..', 'index.html' ) ) && 'zip' !== pathinfo( $file, PATHINFO_EXTENSION ) && false === strpos( $file, '-running' ) ) {
348
-
349
- @unlink( $file );
350
-
351
- }
352
  }
353
 
354
- closedir( $handle );
355
 
356
  }
357
 
358
  }
359
 
360
  }
 
 
 
 
 
 
 
 
4
  * @subpackage BackUpWordPress/classes
5
  */
6
 
7
+ namespace HM\BackUpWordPress;
 
 
 
 
 
 
 
 
8
 
9
  /**
10
  * The Backup Path class
13
  *
14
  * @todo Should be a singleton?
15
  */
16
+ class Path {
17
 
18
  /**
19
  * The path to the directory that backup files are stored in
29
  */
30
  protected $custom_path;
31
 
32
+ private static $instance;
33
+
34
  /**
35
  * Protected constructor to prevent creating a new instance of the
36
  * *Singleton* via the `new` operator from outside of this class.
56
  /**
57
  * Returns the *Singleton* instance of this class.
58
  *
59
+ * @staticvar Path $instance The *Singleton* instances of this class.
60
  *
61
+ * @return Path The *Singleton* instance.
62
  */
63
  public static function get_instance() {
64
 
65
+ if ( ! ( self::$instance instanceof Path ) ) {
66
+ self::$instance = new Path();
 
 
67
  }
68
 
69
+ return self::$instance;
 
70
  }
71
 
72
  /**
82
  // Ensure the backup directory is protected
83
  $this->protect_path();
84
 
85
+ return Backup::conform_dir( $this->path );
86
 
87
  }
88
 
100
 
101
  }
102
 
103
+ public function reset_path() {
104
+ $this->set_path( false );
105
+ }
106
+
107
  /**
108
  * Get the path to the default backup location in wp-content
109
  */
335
  return;
336
  }
337
 
338
+ foreach ( new CleanUpIterator( new \DirectoryIterator( $this->path ) ) as $file ) {
339
 
340
+ if ( $file->isDot() || ! $file->isReadable() || ! $file->isFile() ) {
341
+ continue;
 
 
 
 
 
342
  }
343
 
344
+ @unlink( $file->getPathname() );
345
 
346
  }
347
 
348
  }
349
 
350
  }
351
+
352
+ class CleanUpIterator extends \FilterIterator {
353
+
354
+ // Don't match index.html,files with zip extension or status logfiles.
355
+ public function accept() {
356
+ return ! preg_match( '/(index\.html|.*\.zip|.*-running)/', $this->current() );
357
+ }
358
+ }
classes/class-requirement.php ADDED
@@ -0,0 +1,886 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace HM\BackUpWordPress;
4
+
5
+ /**
6
+ * An abstract requirement class, individual requirements should
7
+ * extend this class
8
+ */
9
+ abstract class Requirement {
10
+
11
+ /**
12
+ * @var string
13
+ */
14
+ protected $name = '';
15
+
16
+ /**
17
+ * @return mixed
18
+ */
19
+ abstract protected function test();
20
+
21
+ /**
22
+ * @return mixed
23
+ */
24
+ public function name() {
25
+ return $this->name;
26
+ }
27
+
28
+ /**
29
+ * @return mixed|string
30
+ */
31
+ public function result() {
32
+
33
+ $test = $this->test();
34
+
35
+ if ( is_string( $test ) && $test )
36
+ return $test;
37
+
38
+ if ( is_bool( $test ) || empty( $test ) ) {
39
+
40
+ if ( $test ) {
41
+ return 'Yes';
42
+ }
43
+
44
+ return 'No';
45
+
46
+ }
47
+
48
+ return var_export( $test, true );
49
+
50
+ }
51
+
52
+ public function raw_result() {
53
+ return $this->test();
54
+ }
55
+
56
+ }
57
+
58
+ /**
59
+ * Class Requirement_Zip_Archive
60
+ */
61
+ class Requirement_Zip_Archive extends Requirement {
62
+
63
+ /**
64
+ * @var string
65
+ */
66
+ var $name = 'ZipArchive';
67
+
68
+ /**
69
+ * @return bool
70
+ */
71
+ protected function test() {
72
+
73
+ if ( class_exists( 'ZipArchive' ) ) {
74
+ return true;
75
+ }
76
+
77
+ return false;
78
+
79
+ }
80
+
81
+ }
82
+
83
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Zip_Archive', 'PHP' );
84
+
85
+ /**
86
+ * Class Requirement_Directory_Iterator_Follow_Symlinks
87
+ *
88
+ * Tests whether the FOLLOW_SYMLINKS class constant is available on Directory Iterator
89
+ */
90
+ class Requirement_Directory_Iterator_Follow_Symlinks extends Requirement {
91
+
92
+ /**
93
+ * @var string
94
+ */
95
+ var $name = 'DirectoryIterator FOLLOW_SYMLINKS';
96
+
97
+ /**
98
+ * @return bool
99
+ */
100
+ protected function test() {
101
+
102
+ if ( defined( 'RecursiveDirectoryIterator::FOLLOW_SYMLINKS' ) ) {
103
+ return true;
104
+ }
105
+
106
+ return false;
107
+
108
+ }
109
+
110
+ }
111
+
112
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Directory_Iterator_Follow_Symlinks', 'PHP' );
113
+
114
+ /**
115
+ * Class Requirement_Zip_Command
116
+ *
117
+ * Tests whether the zip command is available and if it is what path it's available at
118
+ */
119
+ class Requirement_Zip_Command_Path extends Requirement {
120
+
121
+ /**
122
+ * @var string
123
+ */
124
+ var $name = 'zip command';
125
+
126
+ /**
127
+ * @return string
128
+ */
129
+ protected function test() {
130
+
131
+ $hm_backup = new Backup;
132
+
133
+ return $hm_backup->get_zip_command_path();
134
+
135
+ }
136
+
137
+ }
138
+
139
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Zip_Command_Path', 'Server' );
140
+
141
+ /**
142
+ * Class Requirement_Mysqldump_Command
143
+ *
144
+ * Tests whether the zip command is available and if it is what path it's available at
145
+ */
146
+ class Requirement_Mysqldump_Command_Path extends Requirement {
147
+
148
+ /**
149
+ * @var string
150
+ */
151
+ var $name = 'mysqldump command';
152
+
153
+ /**
154
+ * @return string
155
+ */
156
+ protected function test() {
157
+
158
+ $hm_backup = new Backup;
159
+
160
+ return $hm_backup->get_mysqldump_command_path();
161
+
162
+ }
163
+
164
+ }
165
+
166
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Mysqldump_Command_Path', 'Server' );
167
+
168
+ /**
169
+ * Class Requirement_PHP_User
170
+ */
171
+ class Requirement_PHP_User extends Requirement {
172
+
173
+ /**
174
+ * @var string
175
+ */
176
+ var $name = 'User';
177
+
178
+ /**
179
+ * @return string
180
+ */
181
+ protected function test() {
182
+
183
+ if ( ! Backup::is_shell_exec_available() ) {
184
+ return '';
185
+ }
186
+
187
+ return shell_exec( 'whoami' );
188
+
189
+ }
190
+
191
+ }
192
+
193
+ Requirements::register( 'HM\BackUpWordPress\Requirement_PHP_User', 'PHP' );
194
+
195
+ /**
196
+ * Class Requirement_PHP_Group
197
+ */
198
+ class Requirement_PHP_Group extends Requirement {
199
+
200
+ /**
201
+ * @var string
202
+ */
203
+ var $name = 'Group[s]';
204
+
205
+ /**
206
+ * @return string
207
+ */
208
+ protected function test() {
209
+
210
+ if ( ! Backup::is_shell_exec_available() ) {
211
+ return '';
212
+ }
213
+
214
+ return shell_exec( 'groups' );
215
+
216
+ }
217
+
218
+ }
219
+
220
+ Requirements::register( 'HM\BackUpWordPress\Requirement_PHP_Group', 'PHP' );
221
+
222
+ /**
223
+ * Class Requirement_PHP_Version
224
+ */
225
+ class Requirement_PHP_Version extends Requirement {
226
+
227
+ /**
228
+ * @var string
229
+ */
230
+ var $name = 'Version';
231
+
232
+ /**
233
+ * @return string
234
+ */
235
+ protected function test() {
236
+ return PHP_VERSION;
237
+ }
238
+
239
+ }
240
+
241
+ Requirements::register( 'HM\BackUpWordPress\Requirement_PHP_Version', 'PHP' );
242
+
243
+ /**
244
+ * Class Requirement_Cron_Array
245
+ */
246
+ class Requirement_Cron_Array extends Requirement {
247
+
248
+ /**
249
+ * @var string
250
+ */
251
+ var $name = 'Cron Array';
252
+
253
+ /**
254
+ * @return bool|mixed
255
+ */
256
+ protected function test() {
257
+
258
+ $cron = get_option( 'cron' );
259
+
260
+ if ( ! $cron ) {
261
+ return false;
262
+ }
263
+
264
+ return $cron;
265
+
266
+ }
267
+
268
+ }
269
+
270
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Cron_Array', 'Site' );
271
+
272
+ /**
273
+ * Class Requirement_Cron_Array
274
+ */
275
+ class Requirement_Language extends Requirement {
276
+
277
+ /**
278
+ * @var string
279
+ */
280
+ var $name = 'Language';
281
+
282
+ /**
283
+ * @return bool|mixed
284
+ */
285
+ protected function test() {
286
+
287
+ // Since 4.0
288
+ $language = get_option( 'WPLANG' );
289
+
290
+ if ( $language ) {
291
+ return $language;
292
+ }
293
+
294
+ if ( defined( 'WPLANG' ) && WPLANG ) {
295
+ return WPLANG;
296
+ }
297
+
298
+ return 'en_US';
299
+
300
+ }
301
+
302
+ }
303
+
304
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Language', 'Site' );
305
+
306
+ /**
307
+ * Class Requirement_Safe_Mode
308
+ */
309
+ class Requirement_Safe_Mode extends Requirement {
310
+
311
+ /**
312
+ * @var string
313
+ */
314
+ var $name = 'Safe Mode';
315
+
316
+ /**
317
+ * @return bool
318
+ */
319
+ protected function test() {
320
+ return Backup::is_safe_mode_active();
321
+ }
322
+
323
+ }
324
+
325
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Safe_Mode', 'PHP' );
326
+
327
+ /**
328
+ * Class Requirement_Shell_Exec
329
+ */
330
+ class Requirement_Shell_Exec extends Requirement {
331
+
332
+ /**
333
+ * @var string
334
+ */
335
+ var $name = 'Shell Exec';
336
+
337
+ /**
338
+ * @return bool
339
+ */
340
+ protected function test() {
341
+ return Backup::is_shell_exec_available();
342
+ }
343
+
344
+ }
345
+
346
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Shell_Exec', 'PHP' );
347
+
348
+ /**
349
+ * Class Requirement_Memory_Limit
350
+ */
351
+ class Requirement_PHP_Memory_Limit extends Requirement {
352
+
353
+ /**
354
+ * @var string
355
+ */
356
+ var $name = 'Memory Limit';
357
+
358
+ /**
359
+ * @return string
360
+ */
361
+ protected function test() {
362
+ return @ini_get( 'memory_limit' );
363
+ }
364
+
365
+ }
366
+
367
+ Requirements::register( 'HM\BackUpWordPress\Requirement_PHP_Memory_Limit', 'PHP' );
368
+
369
+ /**
370
+ * Class Requirement_Backup_Path
371
+ */
372
+ class Requirement_Backup_Path extends Requirement {
373
+
374
+ /**
375
+ * @var string
376
+ */
377
+ var $name = 'Backup Path';
378
+
379
+ /**
380
+ * @return string
381
+ */
382
+ protected function test() {
383
+ return Path::get_instance()->get_path();
384
+ }
385
+
386
+ }
387
+
388
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Backup_Path', 'Site' );
389
+
390
+ /**
391
+ * Class Requirement_Backup_Path_Permissions
392
+ */
393
+ class Requirement_Backup_Path_Permissions extends Requirement {
394
+
395
+ /**
396
+ * @var string
397
+ */
398
+ var $name = 'Backup Path Permissions';
399
+
400
+ /**
401
+ * @return string
402
+ */
403
+ protected function test() {
404
+ return substr( sprintf( '%o', fileperms( hmbkp_path() ) ), - 4 );
405
+ }
406
+
407
+ }
408
+
409
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Backup_Path_Permissions', 'Site' );
410
+
411
+ /**
412
+ * Class Requirement_WP_CONTENT_DIR
413
+ */
414
+ class Requirement_WP_CONTENT_DIR extends Requirement {
415
+
416
+ /**
417
+ * @var string
418
+ */
419
+ var $name = 'WP_CONTENT_DIR';
420
+
421
+ /**
422
+ * @return string
423
+ */
424
+ protected function test() {
425
+ return WP_CONTENT_DIR;
426
+ }
427
+
428
+ }
429
+
430
+ Requirements::register( 'HM\BackUpWordPress\Requirement_WP_CONTENT_DIR', 'Site' );
431
+
432
+ /**
433
+ * Class Requirement_WP_CONTENT_DIR_Permissions
434
+ */
435
+ class Requirement_WP_CONTENT_DIR_Permissions extends Requirement {
436
+
437
+ /**
438
+ * @var string
439
+ */
440
+ var $name = 'WP_CONTENT_DIR Permissions';
441
+
442
+ /**
443
+ * @return string
444
+ */
445
+ protected function test() {
446
+ return substr( sprintf( '%o', fileperms( WP_CONTENT_DIR ) ), - 4 );
447
+ }
448
+
449
+ }
450
+
451
+ Requirements::register( 'HM\BackUpWordPress\Requirement_WP_CONTENT_DIR_Permissions', 'Site' );
452
+
453
+ /**
454
+ * Class Requirement_ABSPATH
455
+ */
456
+ class Requirement_ABSPATH extends Requirement {
457
+
458
+ /**
459
+ * @var string
460
+ */
461
+ var $name = 'ABSPATH';
462
+
463
+ /**
464
+ * @return string
465
+ */
466
+ protected function test() {
467
+ return ABSPATH;
468
+ }
469
+
470
+ }
471
+
472
+ Requirements::register( 'HM\BackUpWordPress\Requirement_ABSPATH', 'Site' );
473
+
474
+ /**
475
+ * Class Requirement_Backup_Root_Path
476
+ */
477
+ class Requirement_Backup_Root_Path extends Requirement {
478
+
479
+ /**
480
+ * @var string
481
+ */
482
+ var $name = 'Backup Root Path';
483
+
484
+ /**
485
+ * @return string
486
+ */
487
+ protected function test() {
488
+
489
+ $hm_backup = new Backup();
490
+
491
+ return $hm_backup->get_root();
492
+
493
+ }
494
+
495
+ }
496
+
497
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Backup_Root_Path', 'Site' );
498
+
499
+ /**
500
+ * Class Requirement_Calculated_Size
501
+ */
502
+ class Requirement_Calculated_Size extends Requirement {
503
+
504
+ /**
505
+ * @var string
506
+ */
507
+ var $name = 'Calculated size of site';
508
+
509
+ /**
510
+ * @return array
511
+ */
512
+ protected function test() {
513
+
514
+ $backup_sizes = array();
515
+
516
+ $schedules = Schedules::get_instance();
517
+
518
+ foreach ( $schedules->get_schedules() as $schedule ) {
519
+ if ( $schedule->is_site_size_cached() ) {
520
+ $backup_sizes[ $schedule->get_id() ] = $schedule->get_formatted_site_size();
521
+ }
522
+ }
523
+
524
+ return $backup_sizes;
525
+
526
+ }
527
+
528
+ }
529
+
530
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Calculated_Size', 'Site' );
531
+
532
+ /**
533
+ * Class Requirement_WP_Cron_Test_Response
534
+ */
535
+ class Requirement_WP_Cron_Test extends Requirement {
536
+
537
+ /**
538
+ * @var string
539
+ */
540
+ var $name = 'WP Cron Test Failed';
541
+
542
+ /**
543
+ * @return mixed
544
+ */
545
+ protected function test() {
546
+ return (bool) get_option( 'hmbkp_wp_cron_test_failed' );
547
+ }
548
+
549
+ }
550
+
551
+ Requirements::register( 'HM\BackUpWordPress\Requirement_WP_Cron_Test', 'Site' );
552
+
553
+ /**
554
+ * Class Requirement_PHP_API
555
+ */
556
+ class Requirement_PHP_API extends Requirement {
557
+
558
+ /**
559
+ * @var string
560
+ */
561
+ var $name = 'Interface';
562
+
563
+ /**
564
+ * @return string
565
+ */
566
+ protected function test() {
567
+ return php_sapi_name();
568
+ }
569
+
570
+ }
571
+
572
+ Requirements::register( 'HM\BackUpWordPress\Requirement_PHP_API', 'PHP' );
573
+
574
+ /**
575
+ * Class Requirement_Server_Software
576
+ */
577
+ class Requirement_Server_Software extends Requirement {
578
+
579
+ /**
580
+ * @var string
581
+ */
582
+ var $name = 'Server';
583
+
584
+ /**
585
+ * @return bool
586
+ */
587
+ protected function test() {
588
+
589
+ if ( ! empty( $_SERVER['SERVER_SOFTWARE'] ) )
590
+ return $_SERVER['SERVER_SOFTWARE'];
591
+
592
+ return false;
593
+
594
+ }
595
+
596
+ }
597
+
598
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Server_Software', 'Server' );
599
+
600
+ /**
601
+ * Class Requirement_Server_OS
602
+ */
603
+ class Requirement_Server_OS extends Requirement {
604
+
605
+ /**
606
+ * @var string
607
+ */
608
+ var $name = 'OS';
609
+
610
+ /**
611
+ * @return string
612
+ */
613
+ protected function test() {
614
+ return PHP_OS;
615
+ }
616
+
617
+ }
618
+
619
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Server_OS', 'Server' );
620
+
621
+ /**
622
+ * Class Requirement_PHP_Disable_Functions
623
+ */
624
+ class Requirement_PHP_Disable_Functions extends Requirement {
625
+
626
+ /**
627
+ * @var string
628
+ */
629
+ var $name = 'Disabled Functions';
630
+
631
+ /**
632
+ * @return string
633
+ */
634
+ protected function test() {
635
+ return @ini_get( 'disable_functions' );
636
+ }
637
+
638
+ }
639
+
640
+ Requirements::register( 'HM\BackUpWordPress\Requirement_PHP_Disable_Functions', 'PHP' );
641
+
642
+ /**
643
+ * Class Requirement_PHP_Open_Basedir
644
+ */
645
+ class Requirement_PHP_Open_Basedir extends Requirement {
646
+
647
+ /**
648
+ * @var string
649
+ */
650
+ var $name = 'open_basedir';
651
+
652
+ /**
653
+ * @return string
654
+ */
655
+ protected function test() {
656
+ return @ini_get( 'open_basedir' );
657
+ }
658
+
659
+ }
660
+
661
+ Requirements::register( 'HM\BackUpWordPress\Requirement_PHP_Open_Basedir', 'PHP' );
662
+
663
+ /* CONSTANTS */
664
+
665
+ /**
666
+ * Class Requirement_Define_HMBKP_PATH
667
+ */
668
+ class Requirement_Define_HMBKP_PATH extends Requirement {
669
+
670
+ /**
671
+ * @var string
672
+ */
673
+ var $name = 'HMBKP_PATH';
674
+
675
+ /**
676
+ * @return string
677
+ */
678
+ protected function test() {
679
+ return defined( 'HMBKP_PATH' ) ? HMBKP_PATH : '';
680
+ }
681
+
682
+ }
683
+
684
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Define_HMBKP_PATH', 'constants' );
685
+
686
+ /**
687
+ * Class Requirement_Define_HMBKP_ROOT
688
+ */
689
+ class Requirement_Define_HMBKP_ROOT extends Requirement {
690
+
691
+ /**
692
+ * @var string
693
+ */
694
+ var $name = 'HMBKP_ROOT';
695
+
696
+ /**
697
+ * @return string
698
+ */
699
+ protected function test() {
700
+ return defined( 'HMBKP_ROOT' ) ? HMBKP_ROOT : '';
701
+ }
702
+
703
+ }
704
+
705
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Define_HMBKP_ROOT', 'constants' );
706
+
707
+ /**
708
+ * Class Requirement_Define_HMBKP_MYSQLDUMP_PATH
709
+ */
710
+ class Requirement_Define_HMBKP_MYSQLDUMP_PATH extends Requirement {
711
+
712
+ /**
713
+ * @var string
714
+ */
715
+ var $name = 'HMBKP_MYSQLDUMP_PATH';
716
+
717
+ /**
718
+ * @return string
719
+ */
720
+ protected function test() {
721
+ return defined( 'HMBKP_MYSQLDUMP_PATH' ) ? HMBKP_MYSQLDUMP_PATH : '';
722
+ }
723
+
724
+ }
725
+
726
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Define_HMBKP_MYSQLDUMP_PATH', 'constants' );
727
+
728
+ /**
729
+ * Class Requirement_Define_HMBKP_ZIP_PATH
730
+ */
731
+ class Requirement_Define_HMBKP_ZIP_PATH extends Requirement {
732
+
733
+ /**
734
+ * @var string
735
+ */
736
+ var $name = 'HMBKP_ZIP_PATH';
737
+
738
+ /**
739
+ * @return string
740
+ */
741
+ protected function test() {
742
+ return defined( 'HMBKP_ZIP_PATH' ) ? HMBKP_ZIP_PATH : '';
743
+ }
744
+
745
+ }
746
+
747
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Define_HMBKP_ZIP_PATH', 'constants' );
748
+
749
+ /**
750
+ * Class Requirement_Define_HMBKP_CAPABILITY
751
+ */
752
+ class Requirement_Define_HMBKP_CAPABILITY extends Requirement {
753
+
754
+ /**
755
+ * @var string
756
+ */
757
+ var $name = 'HMBKP_CAPABILITY';
758
+
759
+ /**
760
+ * @return string
761
+ */
762
+ protected function test() {
763
+ return defined( 'HMBKP_CAPABILITY' ) ? HMBKP_CAPABILITY : '';
764
+ }
765
+
766
+ }
767
+
768
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Define_HMBKP_CAPABILITY', 'constants' );
769
+
770
+ /**
771
+ * Class Requirement_Define_HMBKP_EMAIL
772
+ */
773
+ class Requirement_Define_HMBKP_EMAIL extends Requirement {
774
+
775
+ /**
776
+ * @var string
777
+ */
778
+ var $name = 'HMBKP_EMAIL';
779
+
780
+ /**
781
+ * @return string
782
+ */
783
+ protected function test() {
784
+ return defined( 'HMBKP_EMAIL' ) ? HMBKP_EMAIL : '';
785
+ }
786
+
787
+ }
788
+
789
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Define_HMBKP_EMAIL', 'constants' );
790
+
791
+ /**
792
+ * Class Requirement_Define_HMBKP_ATTACHMENT_MAX_FILESIZE
793
+ */
794
+ class Requirement_Define_HMBKP_ATTACHMENT_MAX_FILESIZE extends Requirement {
795
+
796
+ /**
797
+ * @var string
798
+ */
799
+ var $name = 'HMBKP_ATTACHMENT_MAX_FILESIZE';
800
+
801
+ /**
802
+ * @return string
803
+ */
804
+ protected function test() {
805
+ return defined( 'HMBKP_ATTACHMENT_MAX_FILESIZE' ) ? HMBKP_ATTACHMENT_MAX_FILESIZE : '';
806
+ }
807
+
808
+ }
809
+
810
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Define_HMBKP_ATTACHMENT_MAX_FILESIZE', 'constants' );
811
+
812
+ /**
813
+ * Class Requirement_Define_HMBKP_EXCLUDE
814
+ */
815
+ class Requirement_Define_HMBKP_EXCLUDE extends Requirement {
816
+
817
+ /**
818
+ * @var string
819
+ */
820
+ var $name = 'HMBKP_EXCLUDE';
821
+
822
+ /**
823
+ * @return string
824
+ */
825
+ protected function test() {
826
+ return defined( 'HMBKP_EXCLUDE' ) ? HMBKP_EXCLUDE : '';
827
+ }
828
+
829
+ }
830
+
831
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Define_HMBKP_EXCLUDE', 'constants' );
832
+
833
+ class Requirement_Active_Plugins extends Requirement {
834
+
835
+ var $name = 'Active Plugins';
836
+
837
+ protected function test(){
838
+ return get_option( 'active_plugins' );
839
+ }
840
+
841
+ }
842
+
843
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Active_Plugins', 'Site' );
844
+
845
+ class Requirement_Home_Url extends Requirement {
846
+
847
+ var $name = 'Home URL';
848
+
849
+ protected function test(){
850
+ return home_url();
851
+ }
852
+
853
+ }
854
+
855
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Home_Url', 'Site' );
856
+
857
+ class Requirement_Site_Url extends Requirement {
858
+
859
+ var $name = 'Site URL';
860
+
861
+ protected function test() {
862
+ return site_url();
863
+ }
864
+
865
+ }
866
+
867
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Site_Url', 'Site' );
868
+
869
+ class Requirement_Plugin_Version extends Requirement {
870
+ var $name = 'Plugin Version';
871
+
872
+ protected function test() {
873
+ return Plugin::PLUGIN_VERSION;
874
+ }
875
+ }
876
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Plugin_Version', 'constants' );
877
+
878
+ class Requirement_Max_Exec extends Requirement {
879
+
880
+ var $name = 'Max execution time';
881
+
882
+ protected function test(){
883
+ return @ini_get( 'max_execution_time' );
884
+ }
885
+ }
886
+ Requirements::register( 'HM\BackUpWordPress\Requirement_Max_Exec', 'PHP' );
classes/class-requirements.php CHANGED
@@ -1,10 +1,12 @@
1
  <?php
2
 
 
 
3
  /**
4
  * A singleton to handle the registering, unregistering
5
  * and storage of individual requirements
6
  */
7
- class HMBKP_Requirements {
8
 
9
  /**
10
  * The array of requirements
@@ -48,13 +50,7 @@ class HMBKP_Requirements {
48
  * @return WP_Error
49
  */
50
  public static function register( $class, $group = 'misc' ) {
51
-
52
- if ( ! class_exists( $class ) ) {
53
- return new WP_Error( 'invalid argument', 'Argument 1 for ' . __METHOD__ . ' must be a valid class' );
54
- }
55
-
56
  self::$requirements[$group][] = $class;
57
-
58
  }
59
 
60
  /**
@@ -66,10 +62,6 @@ class HMBKP_Requirements {
66
  */
67
  private static function instantiate( $class ) {
68
 
69
- if ( ! class_exists( $class ) ) {
70
- return new WP_Error( 'invalid argument', 'Argument 1 for ' . __METHOD__ . ' must be a valid class' );
71
- }
72
-
73
  $$class = new $class;
74
 
75
  return $$class;
@@ -77,912 +69,3 @@ class HMBKP_Requirements {
77
  }
78
 
79
  }
80
-
81
- /**
82
- * An abstract requirement class, individual requirements should
83
- * extend this class
84
- */
85
- abstract class HMBKP_Requirement {
86
-
87
- /**
88
- * @return mixed
89
- */
90
- abstract protected function test();
91
-
92
- /**
93
- * @return mixed
94
- */
95
- public function name() {
96
- return $this->name;
97
- }
98
-
99
- /**
100
- * @return mixed|string
101
- */
102
- public function result() {
103
-
104
- $test = $this->test();
105
-
106
- if ( is_string( $test ) && $test )
107
- return $test;
108
-
109
- if ( is_bool( $test ) || empty( $test ) ) {
110
-
111
- if ( $test ) {
112
- return 'Yes';
113
- }
114
-
115
- return 'No';
116
-
117
- }
118
-
119
- return var_export( $test, true );
120
-
121
- }
122
-
123
- public function raw_result() {
124
- return $this->test();
125
- }
126
-
127
- }
128
-
129
- /**
130
- * Class HMBKP_Requirement_Zip_Archive
131
- */
132
- class HMBKP_Requirement_Zip_Archive extends HMBKP_Requirement {
133
-
134
- /**
135
- * @var string
136
- */
137
- var $name = 'ZipArchive';
138
-
139
- /**
140
- * @return bool
141
- */
142
- protected function test() {
143
-
144
- if ( class_exists( 'ZipArchive' ) ) {
145
- return true;
146
- }
147
-
148
- return false;
149
-
150
- }
151
-
152
- }
153
-
154
- HMBKP_Requirements::register( 'HMBKP_Requirement_Zip_Archive', 'PHP' );
155
-
156
- /**
157
- * Class HMBKP_Requirement_Directory_Iterator_Follow_Symlinks
158
- *
159
- * Tests whether the FOLLOW_SYMLINKS class constant is available on Directory Iterator
160
- */
161
- class HMBKP_Requirement_Directory_Iterator_Follow_Symlinks extends HMBKP_Requirement {
162
-
163
- /**
164
- * @var string
165
- */
166
- var $name = 'DirectoryIterator FOLLOW_SYMLINKS';
167
-
168
- /**
169
- * @return bool
170
- */
171
- protected function test() {
172
-
173
- if ( defined( 'RecursiveDirectoryIterator::FOLLOW_SYMLINKS' ) ) {
174
- return true;
175
- }
176
-
177
- return false;
178
-
179
- }
180
-
181
- }
182
-
183
- HMBKP_Requirements::register( 'HMBKP_Requirement_Directory_Iterator_Follow_Symlinks', 'PHP' );
184
-
185
- /**
186
- * Class HMBKP_Requirement_Zip_Command
187
- *
188
- * Tests whether the zip command is available and if it is what path it's available at
189
- */
190
- class HMBKP_Requirement_Zip_Command_Path extends HMBKP_Requirement {
191
-
192
- /**
193
- * @var string
194
- */
195
- var $name = 'zip command';
196
-
197
- /**
198
- * @return string
199
- */
200
- protected function test() {
201
-
202
- $hm_backup = new HM_Backup;
203
-
204
- return $hm_backup->get_zip_command_path();
205
-
206
- }
207
-
208
- }
209
-
210
- HMBKP_Requirements::register( 'HMBKP_Requirement_Zip_Command_Path', 'Server' );
211
-
212
- /**
213
- * Class HMBKP_Requirement_Mysqldump_Command
214
- *
215
- * Tests whether the zip command is available and if it is what path it's available at
216
- */
217
- class HMBKP_Requirement_Mysqldump_Command_Path extends HMBKP_Requirement {
218
-
219
- /**
220
- * @var string
221
- */
222
- var $name = 'mysqldump command';
223
-
224
- /**
225
- * @return string
226
- */
227
- protected function test() {
228
-
229
- $hm_backup = new HM_Backup;
230
-
231
- return $hm_backup->get_mysqldump_command_path();
232
-
233
- }
234
-
235
- }
236
-
237
- HMBKP_Requirements::register( 'HMBKP_Requirement_Mysqldump_Command_Path', 'Server' );
238
-
239
- /**
240
- * Class HMBKP_Requirement_PHP_User
241
- */
242
- class HMBKP_Requirement_PHP_User extends HMBKP_Requirement {
243
-
244
- /**
245
- * @var string
246
- */
247
- var $name = 'User';
248
-
249
- /**
250
- * @return string
251
- */
252
- protected function test() {
253
-
254
- if ( ! HM_Backup::is_shell_exec_available() ) {
255
- return '';
256
- }
257
-
258
- return trim( shell_exec( 'whoami' ) );
259
-
260
- }
261
-
262
- }
263
-
264
- HMBKP_Requirements::register( 'HMBKP_Requirement_PHP_User', 'PHP' );
265
-
266
- /**
267
- * Class HMBKP_Requirement_PHP_Group
268
- */
269
- class HMBKP_Requirement_PHP_Group extends HMBKP_Requirement {
270
-
271
- /**
272
- * @var string
273
- */
274
- var $name = 'Group[s]';
275
-
276
- /**
277
- * @return string
278
- */
279
- protected function test() {
280
-
281
- if ( ! HM_Backup::is_shell_exec_available() ) {
282
- return '';
283
- }
284
-
285
- return trim( shell_exec( 'groups' ) );
286
-
287
- }
288
-
289
- }
290
-
291
- HMBKP_Requirements::register( 'HMBKP_Requirement_PHP_Group', 'PHP' );
292
-
293
- /**
294
- * Class HMBKP_Requirement_PHP_Version
295
- */
296
- class HMBKP_Requirement_PHP_Version extends HMBKP_Requirement {
297
-
298
- /**
299
- * @var string
300
- */
301
- var $name = 'Version';
302
-
303
- /**
304
- * @return string
305
- */
306
- protected function test() {
307
- return PHP_VERSION;
308
- }
309
-
310
- }
311
-
312
- HMBKP_Requirements::register( 'HMBKP_Requirement_PHP_Version', 'PHP' );
313
-
314
- /**
315
- * Class HMBKP_Requirement_Cron_Array
316
- */
317
- class HMBKP_Requirement_Cron_Array extends HMBKP_Requirement {
318
-
319
- /**
320
- * @var string
321
- */
322
- var $name = 'Cron Array';
323
-
324
- /**
325
- * @return bool|mixed
326
- */
327
- protected function test() {
328
-
329
- $cron = get_option( 'cron' );
330
-
331
- if ( ! $cron ) {
332
- return false;
333
- }
334
-
335
- return json_encode( $cron );
336
-
337
- }
338
-
339
- }
340
-
341
- HMBKP_Requirements::register( 'HMBKP_Requirement_Cron_Array', 'Site' );
342
-
343
- /**
344
- * Class HMBKP_Requirement_Cron_Array
345
- */
346
- class HMBKP_Requirement_Language extends HMBKP_Requirement {
347
-
348
- /**
349
- * @var string
350
- */
351
- var $name = 'Language';
352
-
353
- /**
354
- * @return bool|mixed
355
- */
356
- protected function test() {
357
-
358
- // Since 4.0
359
- $language = get_option( 'WPLANG' );
360
-
361
- if ( $language ) {
362
- return $language;
363
- }
364
-
365
- if ( defined( 'WPLANG' ) && WPLANG ) {
366
- return WPLANG;
367
- }
368
-
369
- return 'en_US';
370
-
371
- }
372
-
373
- }
374
-
375
- HMBKP_Requirements::register( 'HMBKP_Requirement_Language', 'Site' );
376
-
377
- /**
378
- * Class HMBKP_Requirement_Safe_Mode
379
- */
380
- class HMBKP_Requirement_Safe_Mode extends HMBKP_Requirement {
381
-
382
- /**
383
- * @var string
384
- */
385
- var $name = 'Safe Mode';
386
-
387
- /**
388
- * @return bool
389
- */
390
- protected function test() {
391
- return HM_Backup::is_safe_mode_active();
392
- }
393
-
394
- }
395
-
396
- HMBKP_Requirements::register( 'HMBKP_Requirement_Safe_Mode', 'PHP' );
397
-
398
- /**
399
- * Class HMBKP_Requirement_Shell_Exec
400
- */
401
- class HMBKP_Requirement_Shell_Exec extends HMBKP_Requirement {
402
-
403
- /**
404
- * @var string
405
- */
406
- var $name = 'Shell Exec';
407
-
408
- /**
409
- * @return bool
410
- */
411
- protected function test() {
412
- return HM_Backup::is_shell_exec_available();
413
- }
414
-
415
- }
416
-
417
- HMBKP_Requirements::register( 'HMBKP_Requirement_Shell_Exec', 'PHP' );
418
-
419
- /**
420
- * Class HMBKP_Requirement_Memory_Limit
421
- */
422
- class HMBKP_Requirement_PHP_Memory_Limit extends HMBKP_Requirement {
423
-
424
- /**
425
- * @var string
426
- */
427
- var $name = 'Memory Limit';
428
-
429
- /**
430
- * @return string
431
- */
432
- protected function test() {
433
- return @ini_get( 'memory_limit' );
434
- }
435
-
436
- }
437
-
438
- HMBKP_Requirements::register( 'HMBKP_Requirement_PHP_Memory_Limit', 'PHP' );
439
-
440
- /**
441
- * Class HMBKP_Requirement_Backup_Path
442
- */
443
- class HMBKP_Requirement_Backup_Path extends HMBKP_Requirement {
444
-
445
- /**
446
- * @var string
447
- */
448
- var $name = 'Backup Path';
449
-
450
- /**
451
- * @return string
452
- */
453
- protected function test() {
454
- return HMBKP_Path::get_instance()->get_path();
455
- }
456
-
457
- }
458
-
459
- HMBKP_Requirements::register( 'HMBKP_Requirement_Backup_Path', 'Site' );
460
-
461
- /**
462
- * Class HMBKP_Requirement_Backup_Path_Permissions
463
- */
464
- class HMBKP_Requirement_Backup_Path_Permissions extends HMBKP_Requirement {
465
-
466
- /**
467
- * @var string
468
- */
469
- var $name = 'Backup Path Permissions';
470
-
471
- /**
472
- * @return string
473
- */
474
- protected function test() {
475
- return substr( sprintf( '%o', fileperms( hmbkp_path() ) ), - 4 );
476
- }
477
-
478
- }
479
-
480
- HMBKP_Requirements::register( 'HMBKP_Requirement_Backup_Path_Permissions', 'Site' );
481
-
482
- /**
483
- * Class HMBKP_Requirement_WP_CONTENT_DIR
484
- */
485
- class HMBKP_Requirement_WP_CONTENT_DIR extends HMBKP_Requirement {
486
-
487
- /**
488
- * @var string
489
- */
490
- var $name = 'WP_CONTENT_DIR';
491
-
492
- /**
493
- * @return string
494
- */
495
- protected function test() {
496
- return WP_CONTENT_DIR;
497
- }
498
-
499
- }
500
-
501
- HMBKP_Requirements::register( 'HMBKP_Requirement_WP_CONTENT_DIR', 'Site' );
502
-
503
- /**
504
- * Class HMBKP_Requirement_WP_CONTENT_DIR_Permissions
505
- */
506
- class HMBKP_Requirement_WP_CONTENT_DIR_Permissions extends HMBKP_Requirement {
507
-
508
- /**
509
- * @var string
510
- */
511
- var $name = 'WP_CONTENT_DIR Permissions';
512
-
513
- /**
514
- * @return string
515
- */
516
- protected function test() {
517
- return substr( sprintf( '%o', fileperms( WP_CONTENT_DIR ) ), - 4 );
518
- }
519
-
520
- }
521
-
522
- HMBKP_Requirements::register( 'HMBKP_Requirement_WP_CONTENT_DIR_Permissions', 'Site' );
523
-
524
- /**
525
- * Class HMBKP_Requirement_ABSPATH
526
- */
527
- class HMBKP_Requirement_ABSPATH extends HMBKP_Requirement {
528
-
529
- /**
530
- * @var string
531
- */
532
- var $name = 'ABSPATH';
533
-
534
- /**
535
- * @return string
536
- */
537
- protected function test() {
538
- return ABSPATH;
539
- }
540
-
541
- }
542
-
543
- HMBKP_Requirements::register( 'HMBKP_Requirement_ABSPATH', 'Site' );
544
-
545
- /**
546
- * Class HMBKP_Requirement_Backup_Root_Path
547
- */
548
- class HMBKP_Requirement_Backup_Root_Path extends HMBKP_Requirement {
549
-
550
- /**
551
- * @var string
552
- */
553
- var $name = 'Backup Root Path';
554
-
555
- /**
556
- * @return string
557
- */
558
- protected function test() {
559
-
560
- $hm_backup = new HM_Backup();
561
-
562
- return $hm_backup->get_root();
563
-
564
- }
565
-
566
- }
567
-
568
- HMBKP_Requirements::register( 'HMBKP_Requirement_Backup_Root_Path', 'Site' );
569
-
570
- /**
571
- * Class HMBKP_Requirement_Calculated_Size
572
- */
573
- class HMBKP_Requirement_Calculated_Size extends HMBKP_Requirement {
574
-
575
- /**
576
- * @var string
577
- */
578
- var $name = 'Calculated size of site';
579
-
580
- /**
581
- * @return string
582
- */
583
- protected function test() {
584
-
585
- $backup_sizes = array();
586
-
587
- $schedules = HMBKP_Schedules::get_instance();
588
-
589
- foreach ( $schedules->get_schedules() as $schedule ) {
590
- if ( $schedule->is_site_size_cached() ) {
591
- $backup_sizes[ $schedule->get_id() ] = $schedule->get_formatted_site_size();
592
- }
593
- }
594
-
595
- return $backup_sizes;
596
-
597
- }
598
-
599
- }
600
-
601
- HMBKP_Requirements::register( 'HMBKP_Requirement_Calculated_Size', 'Site' );
602
-
603
- /**
604
- * Class HMBKP_Average_Backup_Duration
605
- */
606
- class HMBKP_Average_Backup_Duration extends HMBKP_Requirement {
607
-
608
- protected $name = 'Average backup duration';
609
-
610
- public function __get( $property ) {
611
- return $this->{$property};
612
- }
613
-
614
- /**
615
- * Retrieves the average backup duration for each schedule.
616
- *
617
- * @return array The average backup duration for all schedules.
618
- */
619
- public function test() {
620
-
621
- $schedule_average_durations = array();
622
-
623
- $schedules = HMBKP_Schedules::get_instance();
624
-
625
- foreach ( $schedules->get_schedules() as $schedule ) {
626
- $schedule_average_durations[ sprintf( __( 'Schedule: %s', 'backupwordpress' ), $schedule->get_id() ) ] = sprintf( __( 'Duration: %s', 'backupwordpress' ), $schedule->get_schedule_average_duration() );
627
- }
628
-
629
- return array_filter( $schedule_average_durations );
630
- }
631
- }
632
- HMBKP_Requirements::register( 'HMBKP_Average_Backup_Duration', 'Site' );
633
-
634
- /**
635
- * Class HMBKP_Requirement_WP_Cron_Test_Response
636
- */
637
- class HMBKP_Requirement_WP_Cron_Test extends HMBKP_Requirement {
638
-
639
- /**
640
- * @var string
641
- */
642
- var $name = 'WP Cron Test Failed';
643
-
644
- /**
645
- * @return mixed
646
- */
647
- protected function test() {
648
- return (bool) get_option( 'hmbkp_wp_cron_test_failed' );
649
- }
650
-
651
- }
652
-
653
- HMBKP_Requirements::register( 'HMBKP_Requirement_WP_Cron_Test', 'Site' );
654
-
655
- /**
656
- * Class HMBKP_Requirement_PHP_API
657
- */
658
- class HMBKP_Requirement_PHP_API extends HMBKP_Requirement {
659
-
660
- /**
661
- * @var string
662
- */
663
- var $name = 'Interface';
664
-
665
- /**
666
- * @return string
667
- */
668
- protected function test() {
669
- return php_sapi_name();
670
- }
671
-
672
- }
673
-
674
- HMBKP_Requirements::register( 'HMBKP_Requirement_PHP_API', 'PHP' );
675
-
676
- /**
677
- * Class HMBKP_Requirement_Server_Software
678
- */
679
- class HMBKP_Requirement_Server_Software extends HMBKP_Requirement {
680
-
681
- /**
682
- * @var string
683
- */
684
- var $name = 'Server';
685
-
686
- /**
687
- * @return bool
688
- */
689
- protected function test() {
690
-
691
- if ( ! empty( $_SERVER['SERVER_SOFTWARE'] ) )
692
- return $_SERVER['SERVER_SOFTWARE'];
693
-
694
- return false;
695
-
696
- }
697
-
698
- }
699
-
700
- HMBKP_Requirements::register( 'HMBKP_Requirement_Server_Software', 'Server' );
701
-
702
- /**
703
- * Class HMBKP_Requirement_Server_OS
704
- */
705
- class HMBKP_Requirement_Server_OS extends HMBKP_Requirement {
706
-
707
- /**
708
- * @var string
709
- */
710
- var $name = 'OS';
711
-
712
- /**
713
- * @return string
714
- */
715
- protected function test() {
716
- return PHP_OS;
717
- }
718
-
719
- }
720
-
721
- HMBKP_Requirements::register( 'HMBKP_Requirement_Server_OS', 'Server' );
722
-
723
- /**
724
- * Class HMBKP_Requirement_PHP_Disable_Functions
725
- */
726
- class HMBKP_Requirement_PHP_Disable_Functions extends HMBKP_Requirement {
727
-
728
- /**
729
- * @var string
730
- */
731
- var $name = 'Disabled Functions';
732
-
733
- /**
734
- * @return string
735
- */
736
- protected function test() {
737
- return @ini_get( 'disable_functions' );
738
- }
739
-
740
- }
741
-
742
- HMBKP_Requirements::register( 'HMBKP_Requirement_PHP_Disable_Functions', 'PHP' );
743
-
744
- /**
745
- * Class HMBKP_Requirement_PHP_Open_Basedir
746
- */
747
- class HMBKP_Requirement_PHP_Open_Basedir extends HMBKP_Requirement {
748
-
749
- /**
750
- * @var string
751
- */
752
- var $name = 'open_basedir';
753
-
754
- /**
755
- * @return string
756
- */
757
- protected function test() {
758
- return @ini_get( 'open_basedir' );
759
- }
760
-
761
- }
762
-
763
- HMBKP_Requirements::register( 'HMBKP_Requirement_PHP_Open_Basedir', 'PHP' );
764
-
765
- /* CONSTANTS */
766
-
767
- /**
768
- * Class HMBKP_Requirement_Define_HMBKP_PATH
769
- */
770
- class HMBKP_Requirement_Define_HMBKP_PATH extends HMBKP_Requirement {
771
-
772
- /**
773
- * @var string
774
- */
775
- var $name = 'HMBKP_PATH';
776
-
777
- /**
778
- * @return string
779
- */
780
- protected function test() {
781
- return defined( 'HMBKP_PATH' ) ? HMBKP_PATH : '';
782
- }
783
-
784
- }
785
-
786
- HMBKP_Requirements::register( 'HMBKP_Requirement_Define_HMBKP_PATH', 'constants' );
787
-
788
- /**
789
- * Class HMBKP_Requirement_Define_HMBKP_ROOT
790
- */
791
- class HMBKP_Requirement_Define_HMBKP_ROOT extends HMBKP_Requirement {
792
-
793
- /**
794
- * @var string
795
- */
796
- var $name = 'HMBKP_ROOT';
797
-
798
- /**
799
- * @return string
800
- */
801
- protected function test() {
802
- return defined( 'HMBKP_ROOT' ) ? HMBKP_ROOT : '';
803
- }
804
-
805
- }
806
-
807
- HMBKP_Requirements::register( 'HMBKP_Requirement_Define_HMBKP_ROOT', 'constants' );
808
-
809
- /**
810
- * Class HMBKP_Requirement_Define_HMBKP_MYSQLDUMP_PATH
811
- */
812
- class HMBKP_Requirement_Define_HMBKP_MYSQLDUMP_PATH extends HMBKP_Requirement {
813
-
814
- /**
815
- * @var string
816
- */
817
- var $name = 'HMBKP_MYSQLDUMP_PATH';
818
-
819
- /**
820
- * @return string
821
- */
822
- protected function test() {
823
- return defined( 'HMBKP_MYSQLDUMP_PATH' ) ? HMBKP_MYSQLDUMP_PATH : '';
824
- }
825
-
826
- }
827
-
828
- HMBKP_Requirements::register( 'HMBKP_Requirement_Define_HMBKP_MYSQLDUMP_PATH', 'constants' );
829
-
830
- /**
831
- * Class HMBKP_Requirement_Define_HMBKP_ZIP_PATH
832
- */
833
- class HMBKP_Requirement_Define_HMBKP_ZIP_PATH extends HMBKP_Requirement {
834
-
835
- /**
836
- * @var string
837
- */
838
- var $name = 'HMBKP_ZIP_PATH';
839
-
840
- /**
841
- * @return string
842
- */
843
- protected function test() {
844
- return defined( 'HMBKP_ZIP_PATH' ) ? HMBKP_ZIP_PATH : '';
845
- }
846
-
847
- }
848
-
849
- HMBKP_Requirements::register( 'HMBKP_Requirement_Define_HMBKP_ZIP_PATH', 'constants' );
850
-
851
- /**
852
- * Class HMBKP_Requirement_Define_HMBKP_CAPABILITY
853
- */
854
- class HMBKP_Requirement_Define_HMBKP_CAPABILITY extends HMBKP_Requirement {
855
-
856
- /**
857
- * @var string
858
- */
859
- var $name = 'HMBKP_CAPABILITY';
860
-
861
- /**
862
- * @return string
863
- */
864
- protected function test() {
865
- return defined( 'HMBKP_CAPABILITY' ) ? HMBKP_CAPABILITY : '';
866
- }
867
-
868
- }
869
-
870
- HMBKP_Requirements::register( 'HMBKP_Requirement_Define_HMBKP_CAPABILITY', 'constants' );
871
-
872
- /**
873
- * Class HMBKP_Requirement_Define_HMBKP_EMAIL
874
- */
875
- class HMBKP_Requirement_Define_HMBKP_EMAIL extends HMBKP_Requirement {
876
-
877
- /**
878
- * @var string
879
- */
880
- var $name = 'HMBKP_EMAIL';
881
-
882
- /**
883
- * @return string
884
- */
885
- protected function test() {
886
- return defined( 'HMBKP_EMAIL' ) ? HMBKP_EMAIL : '';
887
- }
888
-
889
- }
890
-
891
- HMBKP_Requirements::register( 'HMBKP_Requirement_Define_HMBKP_EMAIL', 'constants' );
892
-
893
- /**
894
- * Class HMBKP_Requirement_Define_HMBKP_ATTACHMENT_MAX_FILESIZE
895
- */
896
- class HMBKP_Requirement_Define_HMBKP_ATTACHMENT_MAX_FILESIZE extends HMBKP_Requirement {
897
-
898
- /**
899
- * @var string
900
- */
901
- var $name = 'HMBKP_ATTACHMENT_MAX_FILESIZE';
902
-
903
- /**
904
- * @return string
905
- */
906
- protected function test() {
907
- return defined( 'HMBKP_ATTACHMENT_MAX_FILESIZE' ) ? HMBKP_ATTACHMENT_MAX_FILESIZE : '';
908
- }
909
-
910
- }
911
-
912
- HMBKP_Requirements::register( 'HMBKP_Requirement_Define_HMBKP_ATTACHMENT_MAX_FILESIZE', 'constants' );
913
-
914
- /**
915
- * Class HMBKP_Requirement_Define_HMBKP_EXCLUDE
916
- */
917
- class HMBKP_Requirement_Define_HMBKP_EXCLUDE extends HMBKP_Requirement {
918
-
919
- /**
920
- * @var string
921
- */
922
- var $name = 'HMBKP_EXCLUDE';
923
-
924
- /**
925
- * @return string
926
- */
927
- protected function test() {
928
- return defined( 'HMBKP_EXCLUDE' ) ? HMBKP_EXCLUDE : '';
929
- }
930
-
931
- }
932
-
933
- HMBKP_Requirements::register( 'HMBKP_Requirement_Define_HMBKP_EXCLUDE', 'constants' );
934
-
935
- class HMBKP_Requirement_Active_Plugins extends HMBKP_Requirement {
936
-
937
- var $name = 'Active Plugins';
938
-
939
- protected function test(){
940
- return get_option( 'active_plugins' );
941
- }
942
-
943
- }
944
-
945
- HMBKP_Requirements::register( 'HMBKP_Requirement_Active_Plugins', 'Site' );
946
-
947
- class HMBKP_Requirement_Home_Url extends HMBKP_Requirement {
948
-
949
- var $name = 'Home URL';
950
-
951
- protected function test(){
952
- return home_url();
953
- }
954
-
955
- }
956
-
957
- HMBKP_Requirements::register( 'HMBKP_Requirement_Home_Url', 'Site' );
958
-
959
- class HMBKP_Requirement_Site_Url extends HMBKP_Requirement {
960
-
961
- var $name = 'Site URL';
962
-
963
- protected function test() {
964
- return site_url();
965
- }
966
-
967
- }
968
-
969
- HMBKP_Requirements::register( 'HMBKP_Requirement_Site_Url', 'Site' );
970
-
971
- class HMBKP_Requirement_Plugin_Version extends HMBKP_Requirement {
972
- var $name = 'Plugin Version';
973
-
974
- protected function test() {
975
- return BackUpWordPress_Plugin::PLUGIN_VERSION;
976
- }
977
- }
978
- HMBKP_Requirements::register( 'HMBKP_Requirement_Plugin_Version', 'constants' );
979
-
980
- class HMBKP_Requirement_Max_Exec extends HMBKP_Requirement {
981
-
982
- var $name = 'Max execution time';
983
-
984
- protected function test(){
985
- return @ini_get( 'max_execution_time' );
986
- }
987
- }
988
- HMBKP_Requirements::register( 'HMBKP_Requirement_Max_Exec', 'PHP' );
1
  <?php
2
 
3
+ namespace HM\BackUpWordPress;
4
+
5
  /**
6
  * A singleton to handle the registering, unregistering
7
  * and storage of individual requirements
8
  */
9
+ class Requirements {
10
 
11
  /**
12
  * The array of requirements
50
  * @return WP_Error
51
  */
52
  public static function register( $class, $group = 'misc' ) {
 
 
 
 
 
53
  self::$requirements[$group][] = $class;
 
54
  }
55
 
56
  /**
62
  */
63
  private static function instantiate( $class ) {
64
 
 
 
 
 
65
  $$class = new $class;
66
 
67
  return $$class;
69
  }
70
 
71
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/class-schedule.php CHANGED
@@ -1,11 +1,16 @@
1
  <?php
2
 
 
 
3
  /**
4
- * Extend HM Backup with scheduling and backup file management
 
 
5
  *
6
- * @extends HM_Backup
 
7
  */
8
- class HMBKP_Scheduled_Backup extends HM_Backup {
9
 
10
  /**
11
  * The unique schedule id
@@ -31,6 +36,13 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
31
  */
32
  private $options = array();
33
 
 
 
 
 
 
 
 
34
  /**
35
  * Setup the schedule object
36
  * Loads the options from the database and populates properties
@@ -44,52 +56,33 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
44
 
45
  // Verify the schedule id
46
  if ( ! is_string( $id ) || ! trim( $id ) ) {
47
- throw new Exception( 'Argument 1 for ' . __METHOD__ . ' must be a non empty string' );
48
  }
49
 
50
- // Setup HM Backup
51
- parent::__construct();
52
-
53
  // Store id for later
54
  $this->id = $id;
55
 
56
  // Load the options
57
  $this->options = array_filter( (array) get_option( 'hmbkp_schedule_' . $this->get_id() ) );
58
 
59
- // Some properties can be overridden with defines
60
- if ( defined( 'HMBKP_ROOT' ) && HMBKP_ROOT ) {
61
- $this->set_root( HMBKP_ROOT );
62
- }
63
 
64
- if ( defined( 'HMBKP_EXCLUDE' ) && HMBKP_EXCLUDE ) {
65
- parent::set_excludes( HMBKP_EXCLUDE, true );
66
- }
67
-
68
- parent::set_excludes( $this->default_excludes(), true );
69
 
70
- if ( defined( 'HMBKP_MYSQLDUMP_PATH' ) ) {
71
- $this->set_mysqldump_command_path( HMBKP_MYSQLDUMP_PATH );
72
- }
73
 
74
- if ( defined( 'HMBKP_ZIP_PATH' ) ) {
75
- $this->set_zip_command_path( HMBKP_ZIP_PATH );
76
- }
77
 
78
- if ( defined( 'HMBKP_ZIP_PATH' ) && HMBKP_ZIP_PATH === 'PclZip' && $this->skip_zip_archive = true ) {
79
- $this->set_zip_command_path( false );
80
- }
81
 
82
  if ( defined( 'HMBKP_SCHEDULE_START_TIME' ) && strtotime( 'HMBKP_SCHEDULE_START_TIME' ) ) {
83
  $this->set_schedule_start_time( strtotime( 'HMBKP_SCHEDULE_START_TIME' ) );
84
  }
85
 
86
- // Set the path - TODO remove external function dependancy
87
- $this->set_path( hmbkp_path() );
88
-
89
- // Set the archive filename to site name + schedule slug + date
90
- $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' );
91
- $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' );
92
-
93
  // Setup the schedule if it isn't set
94
  if ( ( ! $this->is_cron_scheduled() && $this->get_reoccurrence() !== 'manually' ) ) {
95
  $this->schedule();
@@ -97,10 +90,18 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
97
 
98
  }
99
 
 
 
 
 
 
 
 
 
 
100
  /**
101
  * Get the id for this schedule
102
  *
103
- * @access public
104
  */
105
  public function get_id() {
106
  return esc_attr( $this->id );
@@ -109,7 +110,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
109
  /**
110
  * Get a slugified version of name
111
  *
112
- * @access public
113
  */
114
  public function get_slug() {
115
 
@@ -141,7 +141,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
141
  /**
142
  * Get the name of this backup schedule
143
  *
144
- * @access public
145
  * @return string
146
  */
147
  public function get_name() {
@@ -155,7 +154,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
155
  /**
156
  * Get the type of backup
157
  *
158
- * @access public
159
  * @return string
160
  */
161
  public function get_type() {
@@ -171,8 +169,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
171
  /**
172
  * Set the type of backup
173
  *
174
- * @access public
175
- *
176
  * @param string $type
177
  */
178
  public function set_type( $type ) {
@@ -181,7 +177,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
181
  return;
182
  }
183
 
184
- parent::set_type( $type );
185
 
186
  $this->options['type'] = $type;
187
 
@@ -190,24 +186,21 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
190
  /**
191
  * Get the exclude rules
192
  *
193
- * @access public
194
  * @return array
195
  */
196
  public function get_excludes() {
197
 
198
  if ( ! empty( $this->options['excludes'] ) ) {
199
- parent::set_excludes( $this->options['excludes'] );
200
  }
201
 
202
- return parent::get_excludes();
203
 
204
  }
205
 
206
  /**
207
  * Set the exclude rules
208
  *
209
- * @access public
210
- *
211
  * @param mixed $excludes A comma separated list or array of exclude rules
212
  * @param bool $append Whether to replace or append to existing rules
213
  *
@@ -215,15 +208,15 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
215
  */
216
  public function set_excludes( $excludes, $append = false ) {
217
 
218
- // Use the validation from HM_Backup::set_excludes
219
- parent::set_excludes( $excludes, $append );
220
 
221
  // If these are valid excludes and they are different save them
222
- if ( parent::get_excludes() && ( empty( $this->options['excludes'] ) || $this->options['excludes'] !== parent::get_excludes() ) ) {
223
 
224
- $this->options['excludes'] = $append && ! empty( $this->options['excludes'] ) ? array_merge( (array) $this->options['excludes'], parent::get_excludes() ) : parent::get_excludes();;
225
 
226
- parent::set_excludes( $this->options['excludes'] );
227
 
228
  }
229
 
@@ -232,7 +225,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
232
  /**
233
  * Get the maximum number of backups to keep
234
  *
235
- * @access public
236
  */
237
  public function get_max_backups() {
238
 
@@ -249,12 +242,12 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
249
  *
250
  * @param int $max
251
  *
252
- * @return bool|WP_Error
253
  */
254
  public function set_max_backups( $max ) {
255
 
256
  if ( empty( $max ) || ! is_int( $max ) ) {
257
- return new WP_Error( 'hmbkp_invalid_type_error', sprintf( __( 'Argument 1 for %s must be a valid integer', 'backupwordpress' ), __METHOD__ ) );
258
  }
259
 
260
  $this->options['max_backups'] = $max;
@@ -292,13 +285,9 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
292
 
293
  /**
294
  * Set the service options for this schedule
295
- *
296
- * @access public
297
  */
298
  public function set_service_options( $service, Array $options ) {
299
-
300
  $this->options[ $service ] = $options;
301
-
302
  }
303
 
304
  /**
@@ -306,7 +295,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
306
  *
307
  * Doesn't account for compression
308
  *
309
- * @access public
310
  * @return string
311
  */
312
  public function get_site_size() {
@@ -328,7 +316,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
328
  // Don't include files if database only
329
  if ( 'database' !== $this->get_type() ) {
330
 
331
- $root = new SplFileInfo( $this->get_root() );
332
 
333
  $size += $this->filesize( $root, true );
334
 
@@ -398,7 +386,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
398
  continue;
399
  }
400
 
401
- $file = new SplFileInfo( HM_Backup::conform_dir( trailingslashit( $directory ) . $file_handle ) );
402
 
403
  // Unreadable files are moved to the bottom
404
  if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) {
@@ -472,16 +460,16 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
472
 
473
  }
474
 
475
- $directory_sizes[ $this->get_root() ] = filesize( $this->get_root() );
476
 
477
- $files = $this->get_files();
478
 
479
  foreach ( $files as $file ) {
480
 
481
  if ( $file->isReadable() ) {
482
- $directory_sizes[ $file->getPathname() ] = $file->getSize();
483
  } else {
484
- $directory_sizes[ $file->getPathname() ] = 0;
485
  }
486
 
487
  }
@@ -500,11 +488,11 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
500
  * If $file is a file then just return the result of `filesize()`.
501
  * If $file is a directory then schedule a recursive filesize scan.
502
  *
503
- * @param SplFileInfo $file The file or directory you want to know the size of
504
  * @param bool $skip_excluded_files Skip excluded files when calculating a directories total size
505
  * @return int The total of the file or directory
506
  */
507
- public function filesize( SplFileInfo $file, $skip_excluded_files = false ) {
508
 
509
  // Skip missing or unreadable files
510
  if ( ! file_exists( $file->getPathname() ) || ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) {
@@ -530,7 +518,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
530
  set_transient( 'hmbkp_directory_filesizes_running', true, HOUR_IN_SECONDS );
531
 
532
  // Schedule a Backdrop task to trigger a recalculation
533
- $task = new HM_Backdrop_Task( array( $this, 'recursive_filesize_scanner' ) );
534
  $task->schedule();
535
 
536
  }
@@ -540,7 +528,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
540
  }
541
 
542
  $current_pathname = trailingslashit( $file->getPathname() );
543
- $root = trailingslashit( $this->get_root() );
544
 
545
  foreach ( $directory_sizes as $path => $size ) {
546
 
@@ -553,12 +541,12 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
553
 
554
  if ( $skip_excluded_files ) {
555
 
556
- $excludes = $this->exclude_string( 'regex' );
557
 
558
  foreach ( $directory_sizes as $path => $size ) {
559
 
560
  // Skip excluded files if we have excludes
561
- if ( $excludes && preg_match( '(' . $excludes . ')', str_ireplace( $root, '', HM_Backup::conform_dir( $path ) ) ) ) {
562
  unset( $directory_sizes[ $path ] );
563
  }
564
 
@@ -576,7 +564,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
576
  /**
577
  * Get the start time for the schedule
578
  *
579
- * @access public
580
  * @return int timestamp || 0 for manual only schedules
581
  */
582
  public function get_schedule_start_time( $gmt = true ) {
@@ -609,7 +596,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
609
 
610
  // Don't allow setting the start time in the past
611
  if ( (int) $time <= time() ) {
612
- return new WP_Error( 'hmbkp_invalid_argument_error', sprintf( __( 'Argument 1 for %s must be a valid future timestamp', 'backupwordpress' ), __METHOD__ ) );
613
  }
614
 
615
  $this->options['schedule_start_time'] = $time;
@@ -621,7 +608,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
621
  /**
622
  * Get the schedule reoccurrence
623
  *
624
- * @access public
625
  */
626
  public function get_reoccurrence() {
627
 
@@ -639,7 +625,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
639
  *
640
  * @param string $reoccurrence
641
  *
642
- * @return bool|WP_Error
643
  */
644
  public function set_reoccurrence( $reoccurrence ) {
645
 
@@ -647,7 +633,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
647
 
648
  // Check it's valid
649
  if ( ! is_string( $reoccurrence ) || ! trim( $reoccurrence ) || ( ! in_array( $reoccurrence, array_keys( $hmbkp_schedules ) ) ) && 'manually' !== $reoccurrence ) {
650
- return new WP_Error( 'hmbkp_invalid_argument_error', sprintf( __( 'Argument 1 for %s must be a valid cron reoccurrence or "manually"', 'backupwordpress' ), __METHOD__ ) );
651
  }
652
 
653
  // If the recurrence is already set to the same thing then there's no need to continue
@@ -671,7 +657,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
671
  /**
672
  * Get the interval between backups
673
  *
674
- * @access public
675
  * @return int
676
  */
677
  public function get_interval() {
@@ -708,7 +693,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
708
  /**
709
  * Get the next occurrence of this scheduled backup
710
  *
711
- * @access public
712
  */
713
  public function get_next_occurrence( $gmt = true ) {
714
 
@@ -735,7 +719,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
735
  /**
736
  * Get the path to the backup running file that stores the running backup status
737
  *
738
- * @access public
739
  * @return string
740
  */
741
  public function get_schedule_running_path() {
@@ -745,7 +728,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
745
  /**
746
  * Schedule the backup cron
747
  *
748
- * @access public
749
  */
750
  public function schedule() {
751
 
@@ -762,7 +744,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
762
  /**
763
  * Unschedule the backup cron.
764
  *
765
- * @access public
766
  * @return void
767
  */
768
  public function unschedule() {
@@ -772,7 +753,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
772
  /**
773
  * Run the backup
774
  *
775
- * @access public
776
  */
777
  public function run() {
778
 
@@ -787,7 +767,18 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
787
  // Delete old backups now in-case we fatal error during the backup process
788
  $this->delete_old_backups();
789
 
790
- $this->backup();
 
 
 
 
 
 
 
 
 
 
 
791
 
792
  // Delete the backup running file
793
  if ( file_exists( $this->get_schedule_running_path() ) ) {
@@ -802,7 +793,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
802
  /**
803
  * Get the filename that the running status is stored in.
804
  *
805
- * @access public
806
  * @return string
807
  */
808
  public function get_running_backup_filename() {
@@ -824,7 +814,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
824
  /**
825
  * Get the status of the running backup.
826
  *
827
- * @access public
828
  * @return string
829
  */
830
  public function get_status() {
@@ -847,22 +836,19 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
847
  /**
848
  * Set the status of the running backup
849
  *
850
- * @access public
851
- *
852
  * @param string $message
853
- *
854
- * @return void
855
  */
856
  public function set_status( $message ) {
857
 
858
  $status = json_encode( (object) array(
859
- 'filename' => $this->get_archive_filename(),
860
  'started' => $this->get_schedule_running_start_time(),
861
  'status' => $message,
862
  ) );
863
 
864
  if ( false === @file_put_contents( $this->get_schedule_running_path(), $status ) ) {
865
- throw new RuntimeException( sprintf( __( 'Error writing to file. (%s)', 'backpwordpress' ), $this->get_schedule_running_path() ) );
866
  }
867
 
868
  }
@@ -870,7 +856,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
870
  /**
871
  * Set the time that the current running backup was started
872
  *
873
- * @access public
874
  * @return int $timestamp
875
  */
876
  public function get_schedule_running_start_time() {
@@ -890,40 +875,43 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
890
  }
891
 
892
  /**
893
- * Hook into the actions fired in HM Backup and set the status
894
  *
895
  * @param $action
896
  */
897
- protected function do_action( $action ) {
898
 
899
  // Pass the actions to all the services
900
- foreach ( HMBKP_Services::get_services( $this ) as $service ) {
901
- $service->action( $action );
 
902
  }
903
 
904
- // Fire the parent function as well
905
- parent::do_action( $action );
906
-
907
  switch ( $action ) :
908
 
 
 
 
 
 
909
  case 'hmbkp_mysqldump_started' :
910
 
911
- $this->set_status( sprintf( __( 'Dumping Database %s', 'backupwordpress' ), '(<code>' . $this->get_mysqldump_method() . '</code>)' ) );
912
  break;
913
 
914
  case 'hmbkp_mysqldump_verify_started' :
915
 
916
- $this->set_status( sprintf( __( 'Verifying Database Dump %s', 'backupwordpress' ), '(<code>' . $this->get_mysqldump_method() . '</code>)' ) );
917
  break;
918
 
919
  case 'hmbkp_archive_started' :
920
 
921
- $this->set_status( sprintf( __( 'Creating zip archive %s', 'backupwordpress' ), '(<code>' . $this->get_archive_method() . '</code>)' ) );
922
  break;
923
 
924
  case 'hmbkp_archive_verify_started' :
925
 
926
- $this->set_status( sprintf( __( 'Verifying Zip Archive %s', 'backupwordpress' ), '(<code>' . $this->get_archive_method() . '</code>)' ) );
927
  break;
928
 
929
  case 'hmbkp_backup_complete' :
@@ -935,7 +923,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
935
 
936
  case 'hmbkp_error' :
937
 
938
- if ( $this->get_errors() ) {
939
 
940
  $file = $this->get_path() . '/.backup_errors';
941
 
@@ -947,7 +935,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
947
  return;
948
  }
949
 
950
- fwrite( $handle, json_encode( $this->get_errors() ) );
951
 
952
  fclose( $handle );
953
 
@@ -957,7 +945,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
957
 
958
  case 'hmbkp_warning' :
959
 
960
- if ( $this->get_warnings() ) {
961
 
962
  $file = $this->get_path() . '/.backup_warnings';
963
 
@@ -969,7 +957,7 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
969
  return;
970
  }
971
 
972
- fwrite( $handle, json_encode( $this->get_warnings() ) );
973
 
974
  fclose( $handle );
975
 
@@ -977,9 +965,12 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
977
 
978
  break;
979
 
 
 
 
 
980
  endswitch;
981
 
982
- do_action( 'hmbkp_action_complete', $action, $this );
983
  }
984
 
985
  /**
@@ -1059,7 +1050,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
1059
  * Get the backups created by this schedule
1060
  *
1061
  * @todo look into using recursiveDirectoryIterator and recursiveRegexIterator
1062
- * @access public
1063
  * @return string[] - file paths of the backups
1064
  */
1065
  public function get_backups() {
@@ -1106,23 +1096,23 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
1106
  *
1107
  * @param string $filepath
1108
  *
1109
- * @return bool|WP_Error
1110
  */
1111
  public function delete_backup( $filepath ) {
1112
 
1113
  // Check that it's a valid filepath
1114
  if ( empty( $filepath ) || ! is_string( $filepath ) ) {
1115
- return new WP_Error( 'hmbkp_empty_string_error', sprintf( __( 'Argument 1 for %s must be a non empty string', 'backupwordpress' ), __METHOD__ ) );
1116
  }
1117
 
1118
  // Make sure it exists
1119
  if ( ! file_exists( $filepath ) ) {
1120
- return new WP_Error( 'hmbkp_file_error', sprintf( __( '%s doesn\'t exist', 'backupwordpress' ), $filepath ) );
1121
  }
1122
 
1123
  // Make sure it was created by this schedule
1124
  if ( strpos( $filepath, $this->get_id() ) === false ) {
1125
- return new WP_Error( 'hmbkp_backup_error', __( 'That backup wasn\'t created by this schedule', 'backupwordpress' ) );
1126
  }
1127
 
1128
  unlink( $filepath );
@@ -1134,7 +1124,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
1134
  /**
1135
  * Delete all back up files created by this schedule
1136
  *
1137
- * @access public
1138
  */
1139
  public function delete_backups() {
1140
 
@@ -1145,7 +1134,6 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
1145
  /**
1146
  * Save the schedules options.
1147
  *
1148
- * @access public
1149
  */
1150
  public function save() {
1151
 
@@ -1160,12 +1148,11 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
1160
  * Cancel this schedule
1161
  *
1162
  * Cancels the cron job, removes the schedules options
1163
- * and optionally deletes all backups crated by
1164
  * this schedule.
1165
  *
1166
- * @access public
1167
  */
1168
- public function cancel() {
1169
 
1170
  // Delete the schedule options
1171
  delete_option( 'hmbkp_schedule_' . $this->get_id() );
@@ -1174,7 +1161,9 @@ class HMBKP_Scheduled_Backup extends HM_Backup {
1174
  $this->unschedule();
1175
 
1176
  // Delete it's backups
1177
- $this->delete_backups();
 
 
1178
 
1179
  }
1180
 
1
  <?php
2
 
3
+ namespace HM\BackUpWordPress;
4
+
5
  /**
6
+ * The Backup Scheduler
7
+ *
8
+ * Handles everything related to managing and running a backup schedule
9
  *
10
+ * @uses Backup
11
+ * @uses
12
  */
13
+ class Scheduled_Backup {
14
 
15
  /**
16
  * The unique schedule id
36
  */
37
  private $options = array();
38
 
39
+ /**
40
+ * The Backup instance
41
+ *
42
+ * @var Backup
43
+ */
44
+ public $backup;
45
+
46
  /**
47
  * Setup the schedule object
48
  * Loads the options from the database and populates properties
56
 
57
  // Verify the schedule id
58
  if ( ! is_string( $id ) || ! trim( $id ) ) {
59
+ throw new \Exception( 'Argument 1 for ' . __METHOD__ . ' must be a non empty string' );
60
  }
61
 
 
 
 
62
  // Store id for later
63
  $this->id = $id;
64
 
65
  // Load the options
66
  $this->options = array_filter( (array) get_option( 'hmbkp_schedule_' . $this->get_id() ) );
67
 
68
+ // Setup The Backup class
69
+ $this->backup = new Backup();
 
 
70
 
71
+ // Set the archive filename to site name + schedule slug + date
72
+ $this->backup->set_archive_filename( implode( '-', array( sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ), $this->get_id(), $this->get_type(), current_time( 'Y-m-d-H-i-s' ) ) ) . '.zip' );
 
 
 
73
 
74
+ $this->backup->set_database_dump_filename( implode( '-', array( 'database', sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ), $this->get_id() ) ) . '.sql' );
 
 
75
 
76
+ $this->backup->set_type( $this->get_type() );
77
+ $this->backup->set_excludes( $this->default_excludes(), true );
78
+ $this->backup->set_excludes( $this->get_excludes() );
79
 
80
+ $this->backup->set_action_callback( array( $this, 'do_action' ) );
 
 
81
 
82
  if ( defined( 'HMBKP_SCHEDULE_START_TIME' ) && strtotime( 'HMBKP_SCHEDULE_START_TIME' ) ) {
83
  $this->set_schedule_start_time( strtotime( 'HMBKP_SCHEDULE_START_TIME' ) );
84
  }
85
 
 
 
 
 
 
 
 
86
  // Setup the schedule if it isn't set
87
  if ( ( ! $this->is_cron_scheduled() && $this->get_reoccurrence() !== 'manually' ) ) {
88
  $this->schedule();
90
 
91
  }
92
 
93
+ /**
94
+ * Simple class wrapper for Path::get_path()
95
+ *
96
+ * @return string
97
+ */
98
+ private function get_path() {
99
+ return Path::get_instance()->get_path();
100
+ }
101
+
102
  /**
103
  * Get the id for this schedule
104
  *
 
105
  */
106
  public function get_id() {
107
  return esc_attr( $this->id );
110
  /**
111
  * Get a slugified version of name
112
  *
 
113
  */
114
  public function get_slug() {
115
 
141
  /**
142
  * Get the name of this backup schedule
143
  *
 
144
  * @return string
145
  */
146
  public function get_name() {
154
  /**
155
  * Get the type of backup
156
  *
 
157
  * @return string
158
  */
159
  public function get_type() {
169
  /**
170
  * Set the type of backup
171
  *
 
 
172
  * @param string $type
173
  */
174
  public function set_type( $type ) {
177
  return;
178
  }
179
 
180
+ $this->backup->set_type( $type );
181
 
182
  $this->options['type'] = $type;
183
 
186
  /**
187
  * Get the exclude rules
188
  *
 
189
  * @return array
190
  */
191
  public function get_excludes() {
192
 
193
  if ( ! empty( $this->options['excludes'] ) ) {
194
+ $this->backup->set_excludes( $this->options['excludes'] );
195
  }
196
 
197
+ return $this->backup->get_excludes();
198
 
199
  }
200
 
201
  /**
202
  * Set the exclude rules
203
  *
 
 
204
  * @param mixed $excludes A comma separated list or array of exclude rules
205
  * @param bool $append Whether to replace or append to existing rules
206
  *
208
  */
209
  public function set_excludes( $excludes, $append = false ) {
210
 
211
+ // Use the validation from Backup::set_excludes
212
+ $this->backup->set_excludes( $excludes, $append );
213
 
214
  // If these are valid excludes and they are different save them
215
+ if ( $this->backup->get_excludes() && ( empty( $this->options['excludes'] ) || $this->options['excludes'] !== $this->backup->get_excludes() ) ) {
216
 
217
+ $this->options['excludes'] = $append && ! empty( $this->options['excludes'] ) ? array_merge( (array) $this->options['excludes'], $this->backup->get_excludes() ) : $this->backup->get_excludes();;
218
 
219
+ $this->backup->set_excludes( $this->options['excludes'] );
220
 
221
  }
222
 
225
  /**
226
  * Get the maximum number of backups to keep
227
  *
228
+ * @return int
229
  */
230
  public function get_max_backups() {
231
 
242
  *
243
  * @param int $max
244
  *
245
+ * @return WP_Error|boolean
246
  */
247
  public function set_max_backups( $max ) {
248
 
249
  if ( empty( $max ) || ! is_int( $max ) ) {
250
+ return new \WP_Error( 'hmbkp_invalid_type_error', sprintf( __( 'Argument 1 for %s must be a valid integer', 'backupwordpress' ), __METHOD__ ) );
251
  }
252
 
253
  $this->options['max_backups'] = $max;
285
 
286
  /**
287
  * Set the service options for this schedule
 
 
288
  */
289
  public function set_service_options( $service, Array $options ) {
 
290
  $this->options[ $service ] = $options;
 
291
  }
292
 
293
  /**
295
  *
296
  * Doesn't account for compression
297
  *
 
298
  * @return string
299
  */
300
  public function get_site_size() {
316
  // Don't include files if database only
317
  if ( 'database' !== $this->get_type() ) {
318
 
319
+ $root = new \SplFileInfo( $this->backup->get_root() );
320
 
321
  $size += $this->filesize( $root, true );
322
 
386
  continue;
387
  }
388
 
389
+ $file = new \SplFileInfo( Backup::conform_dir( trailingslashit( $directory ) . $file_handle ) );
390
 
391
  // Unreadable files are moved to the bottom
392
  if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) {
460
 
461
  }
462
 
463
+ $directory_sizes[ $this->backup->get_root() ] = filesize( $this->backup->get_root() );
464
 
465
+ $files = $this->backup->get_files();
466
 
467
  foreach ( $files as $file ) {
468
 
469
  if ( $file->isReadable() ) {
470
+ $directory_sizes[ Backup::conform_dir( $file->getPathname() ) ] = $file->getSize();
471
  } else {
472
+ $directory_sizes[ Backup::conform_dir( $file->getPathname() ) ] = 0;
473
  }
474
 
475
  }
488
  * If $file is a file then just return the result of `filesize()`.
489
  * If $file is a directory then schedule a recursive filesize scan.
490
  *
491
+ * @param \SplFileInfo $file The file or directory you want to know the size of
492
  * @param bool $skip_excluded_files Skip excluded files when calculating a directories total size
493
  * @return int The total of the file or directory
494
  */
495
+ public function filesize( \SplFileInfo $file, $skip_excluded_files = false ) {
496
 
497
  // Skip missing or unreadable files
498
  if ( ! file_exists( $file->getPathname() ) || ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) {
518
  set_transient( 'hmbkp_directory_filesizes_running', true, HOUR_IN_SECONDS );
519
 
520
  // Schedule a Backdrop task to trigger a recalculation
521
+ $task = new \HM\Backdrop\Task( array( $this, 'recursive_filesize_scanner' ) );
522
  $task->schedule();
523
 
524
  }
528
  }
529
 
530
  $current_pathname = trailingslashit( $file->getPathname() );
531
+ $root = trailingslashit( $this->backup->get_root() );
532
 
533
  foreach ( $directory_sizes as $path => $size ) {
534
 
541
 
542
  if ( $skip_excluded_files ) {
543
 
544
+ $excludes = $this->backup->exclude_string( 'regex' );
545
 
546
  foreach ( $directory_sizes as $path => $size ) {
547
 
548
  // Skip excluded files if we have excludes
549
+ if ( $excludes && preg_match( '(' . $excludes . ')', str_ireplace( $root, '', Backup::conform_dir( $path ) ) ) ) {
550
  unset( $directory_sizes[ $path ] );
551
  }
552
 
564
  /**
565
  * Get the start time for the schedule
566
  *
 
567
  * @return int timestamp || 0 for manual only schedules
568
  */
569
  public function get_schedule_start_time( $gmt = true ) {
596
 
597
  // Don't allow setting the start time in the past
598
  if ( (int) $time <= time() ) {
599
+ return new \WP_Error( 'hmbkp_invalid_argument_error', sprintf( __( 'Argument 1 for %s must be a valid future timestamp', 'backupwordpress' ), __METHOD__ ) );
600
  }
601
 
602
  $this->options['schedule_start_time'] = $time;
608
  /**
609
  * Get the schedule reoccurrence
610
  *
 
611
  */
612
  public function get_reoccurrence() {
613
 
625
  *
626
  * @param string $reoccurrence
627
  *
628
+ * @return \WP_Error|null|boolean
629
  */
630
  public function set_reoccurrence( $reoccurrence ) {
631
 
633
 
634
  // Check it's valid
635
  if ( ! is_string( $reoccurrence ) || ! trim( $reoccurrence ) || ( ! in_array( $reoccurrence, array_keys( $hmbkp_schedules ) ) ) && 'manually' !== $reoccurrence ) {
636
+ return new \WP_Error( 'hmbkp_invalid_argument_error', sprintf( __( 'Argument 1 for %s must be a valid cron reoccurrence or "manually"', 'backupwordpress' ), __METHOD__ ) );
637
  }
638
 
639
  // If the recurrence is already set to the same thing then there's no need to continue
657
  /**
658
  * Get the interval between backups
659
  *
 
660
  * @return int
661
  */
662
  public function get_interval() {
693
  /**
694
  * Get the next occurrence of this scheduled backup
695
  *
 
696
  */
697
  public function get_next_occurrence( $gmt = true ) {
698
 
719
  /**
720
  * Get the path to the backup running file that stores the running backup status
721
  *
 
722
  * @return string
723
  */
724
  public function get_schedule_running_path() {
728
  /**
729
  * Schedule the backup cron
730
  *
 
731
  */
732
  public function schedule() {
733
 
744
  /**
745
  * Unschedule the backup cron.
746
  *
 
747
  * @return void
748
  */
749
  public function unschedule() {
753
  /**
754
  * Run the backup
755
  *
 
756
  */
757
  public function run() {
758
 
767
  // Delete old backups now in-case we fatal error during the backup process
768
  $this->delete_old_backups();
769
 
770
+ if ( $this->get_backups() ) {
771
+
772
+ // If we already have a previous backup then pass it in so it can be re-used
773
+ list( $existing_backup ) = array_values( $this->get_backups() );
774
+
775
+ if ( $existing_backup && file_exists( $existing_backup ) ) {
776
+ $this->backup->set_existing_archive_filepath( $existing_backup );
777
+ }
778
+
779
+ }
780
+
781
+ $this->backup->backup();
782
 
783
  // Delete the backup running file
784
  if ( file_exists( $this->get_schedule_running_path() ) ) {
793
  /**
794
  * Get the filename that the running status is stored in.
795
  *
 
796
  * @return string
797
  */
798
  public function get_running_backup_filename() {
814
  /**
815
  * Get the status of the running backup.
816
  *
 
817
  * @return string
818
  */
819
  public function get_status() {
836
  /**
837
  * Set the status of the running backup
838
  *
 
 
839
  * @param string $message
840
+ * @return null
 
841
  */
842
  public function set_status( $message ) {
843
 
844
  $status = json_encode( (object) array(
845
+ 'filename' => $this->backup->get_archive_filename(),
846
  'started' => $this->get_schedule_running_start_time(),
847
  'status' => $message,
848
  ) );
849
 
850
  if ( false === @file_put_contents( $this->get_schedule_running_path(), $status ) ) {
851
+ throw new \RuntimeException( sprintf( __( 'Error writing to file. (%s)', 'backpwordpress' ), $this->get_schedule_running_path() ) );
852
  }
853
 
854
  }
856
  /**
857
  * Set the time that the current running backup was started
858
  *
 
859
  * @return int $timestamp
860
  */
861
  public function get_schedule_running_start_time() {
875
  }
876
 
877
  /**
878
+ * Hook into the actions fired in the Backup class and set the status
879
  *
880
  * @param $action
881
  */
882
+ public function do_action( $action, Backup $backup ) {
883
 
884
  // Pass the actions to all the services
885
+ // Todo should be decoupled into the service class
886
+ foreach ( Services::get_services( $this ) as $service ) {
887
+ $service->action( $action, $backup );
888
  }
889
 
 
 
 
890
  switch ( $action ) :
891
 
892
+ case 'hmbkp_backup_started':
893
+ case 'hmbkp_mysqldump_finished':
894
+ case 'hmbkp_archive_finished':
895
+ break;
896
+
897
  case 'hmbkp_mysqldump_started' :
898
 
899
+ $this->set_status( sprintf( __( 'Dumping Database %s', 'backupwordpress' ), '(<code>' . $this->backup->get_mysqldump_method() . '</code>)' ) );
900
  break;
901
 
902
  case 'hmbkp_mysqldump_verify_started' :
903
 
904
+ $this->set_status( sprintf( __( 'Verifying Database Dump %s', 'backupwordpress' ), '(<code>' . $this->backup->get_mysqldump_method() . '</code>)' ) );
905
  break;
906
 
907
  case 'hmbkp_archive_started' :
908
 
909
+ $this->set_status( sprintf( __( 'Creating zip archive %s', 'backupwordpress' ), '(<code>' . $this->backup->get_archive_method() . '</code>)' ) );
910
  break;
911
 
912
  case 'hmbkp_archive_verify_started' :
913
 
914
+ $this->set_status( sprintf( __( 'Verifying Zip Archive %s', 'backupwordpress' ), '(<code>' . $this->backup->get_archive_method() . '</code>)' ) );
915
  break;
916
 
917
  case 'hmbkp_backup_complete' :
923
 
924
  case 'hmbkp_error' :
925
 
926
+ if ( $this->backup->get_errors() ) {
927
 
928
  $file = $this->get_path() . '/.backup_errors';
929
 
935
  return;
936
  }
937
 
938
+ fwrite( $handle, json_encode( $this->backup->get_errors() ) );
939
 
940
  fclose( $handle );
941
 
945
 
946
  case 'hmbkp_warning' :
947
 
948
+ if ( $this->backup->get_warnings() ) {
949
 
950
  $file = $this->get_path() . '/.backup_warnings';
951
 
957
  return;
958
  }
959
 
960
+ fwrite( $handle, json_encode( $this->backup->get_warnings() ) );
961
 
962
  fclose( $handle );
963
 
965
 
966
  break;
967
 
968
+ default:
969
+
970
+ return new \WP_Error( 'unexpected-error', __( 'An unexpected error occured', 'backupwordpress' ) );
971
+
972
  endswitch;
973
 
 
974
  }
975
 
976
  /**
1050
  * Get the backups created by this schedule
1051
  *
1052
  * @todo look into using recursiveDirectoryIterator and recursiveRegexIterator
 
1053
  * @return string[] - file paths of the backups
1054
  */
1055
  public function get_backups() {
1096
  *
1097
  * @param string $filepath
1098
  *
1099
+ * @return \WP_Error|boolean
1100
  */
1101
  public function delete_backup( $filepath ) {
1102
 
1103
  // Check that it's a valid filepath
1104
  if ( empty( $filepath ) || ! is_string( $filepath ) ) {
1105
+ return new \WP_Error( 'hmbkp_empty_string_error', sprintf( __( 'Argument 1 for %s must be a non empty string', 'backupwordpress' ), __METHOD__ ) );
1106
  }
1107
 
1108
  // Make sure it exists
1109
  if ( ! file_exists( $filepath ) ) {
1110
+ return new \WP_Error( 'hmbkp_file_error', sprintf( __( '%s doesn\'t exist', 'backupwordpress' ), $filepath ) );
1111
  }
1112
 
1113
  // Make sure it was created by this schedule
1114
  if ( strpos( $filepath, $this->get_id() ) === false ) {
1115
+ return new \WP_Error( 'hmbkp_backup_error', __( 'That backup wasn\'t created by this schedule', 'backupwordpress' ) );
1116
  }
1117
 
1118
  unlink( $filepath );
1124
  /**
1125
  * Delete all back up files created by this schedule
1126
  *
 
1127
  */
1128
  public function delete_backups() {
1129
 
1134
  /**
1135
  * Save the schedules options.
1136
  *
 
1137
  */
1138
  public function save() {
1139
 
1148
  * Cancel this schedule
1149
  *
1150
  * Cancels the cron job, removes the schedules options
1151
+ * and optionally deletes all backups created by
1152
  * this schedule.
1153
  *
 
1154
  */
1155
+ public function cancel( $delete_backups = false ) {
1156
 
1157
  // Delete the schedule options
1158
  delete_option( 'hmbkp_schedule_' . $this->get_id() );
1161
  $this->unschedule();
1162
 
1163
  // Delete it's backups
1164
+ if ( $delete_backups ) {
1165
+ $this->delete_backups();
1166
+ }
1167
 
1168
  }
1169
 
classes/class-schedules.php CHANGED
@@ -1,9 +1,11 @@
1
  <?php
2
 
 
 
3
  /**
4
  * A simple class for loading schedules
5
  */
6
- class HMBKP_Schedules {
7
 
8
  /**
9
  * An array of schedules
@@ -20,8 +22,8 @@ class HMBKP_Schedules {
20
 
21
  public static function get_instance() {
22
 
23
- if ( ! self::$instance ) {
24
- self::$instance = new self;
25
  }
26
 
27
  return self::$instance;
@@ -31,7 +33,6 @@ class HMBKP_Schedules {
31
  /**
32
  * Load the schedules from wp_options and store in $this->schedules
33
  *
34
- * @access public
35
  */
36
  private function __construct() {
37
  $this->refresh_schedules();
@@ -44,7 +45,7 @@ class HMBKP_Schedules {
44
  // Load all schedule options from the database
45
  $schedules = $wpdb->get_col( "SELECT option_name from $wpdb->options WHERE option_name LIKE 'hmbkp\_schedule\_%'" );
46
 
47
- // Instantiate each one as a HMBKP_Scheduled_Backup
48
  $this->schedules = array_map( array( $this, 'instantiate' ), array_filter( (array) $schedules ) );
49
 
50
  }
@@ -52,8 +53,7 @@ class HMBKP_Schedules {
52
  /**
53
  * Get an array of schedules
54
  *
55
- * @access public
56
- * @return array
57
  */
58
  public function get_schedules() {
59
  return $this->schedules;
@@ -63,13 +63,15 @@ class HMBKP_Schedules {
63
  * Get a schedule by ID
64
  *
65
  * @param $id
66
- * @return HMBKP_Scheduled_Backup
67
  */
68
  public function get_schedule( $id ) {
69
 
70
- foreach ( $this->schedules as $schedule )
71
- if ( $schedule->get_id() == $id )
72
  return $schedule;
 
 
73
 
74
  return null;
75
  }
@@ -79,10 +81,10 @@ class HMBKP_Schedules {
79
  *
80
  * @access private
81
  * @param string $id
82
- * @return array An array of HMBKP_Scheduled_Backup objects
83
  */
84
  private function instantiate( $id ) {
85
- return new HMBKP_Scheduled_Backup( str_replace( 'hmbkp_schedule_', '', $id ) );
86
  }
87
 
88
  }
1
  <?php
2
 
3
+ namespace HM\BackUpWordPress;
4
+
5
  /**
6
  * A simple class for loading schedules
7
  */
8
+ class Schedules {
9
 
10
  /**
11
  * An array of schedules
22
 
23
  public static function get_instance() {
24
 
25
+ if ( ! ( self::$instance instanceof Schedules ) ) {
26
+ self::$instance = new Schedules();
27
  }
28
 
29
  return self::$instance;
33
  /**
34
  * Load the schedules from wp_options and store in $this->schedules
35
  *
 
36
  */
37
  private function __construct() {
38
  $this->refresh_schedules();
45
  // Load all schedule options from the database
46
  $schedules = $wpdb->get_col( "SELECT option_name from $wpdb->options WHERE option_name LIKE 'hmbkp\_schedule\_%'" );
47
 
48
+ // Instantiate each one as a Scheduled_Backup
49
  $this->schedules = array_map( array( $this, 'instantiate' ), array_filter( (array) $schedules ) );
50
 
51
  }
53
  /**
54
  * Get an array of schedules
55
  *
56
+ * @return Scheduled_Backup[]
 
57
  */
58
  public function get_schedules() {
59
  return $this->schedules;
63
  * Get a schedule by ID
64
  *
65
  * @param $id
66
+ * @return Scheduled_Backup
67
  */
68
  public function get_schedule( $id ) {
69
 
70
+ foreach ( $this->schedules as $schedule ) {
71
+ if ( $schedule->get_id() == $id ) {
72
  return $schedule;
73
+ }
74
+ }
75
 
76
  return null;
77
  }
81
  *
82
  * @access private
83
  * @param string $id
84
+ * @return Scheduled_Backup
85
  */
86
  private function instantiate( $id ) {
87
+ return new Scheduled_Backup( str_replace( 'hmbkp_schedule_', '', $id ) );
88
  }
89
 
90
  }
classes/class-service.php ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace HM\BackUpWordPress;
4
+
5
+ /**
6
+ * An abstract service class, individual services should
7
+ * extend this class
8
+ */
9
+ abstract class Service {
10
+
11
+ /**
12
+ * Human readable name for this service
13
+ * @var string
14
+ */
15
+ public $name;
16
+
17
+ /**
18
+ * The instance Backup_Schedule that this service is
19
+ * is currently working with
20
+ *
21
+ * @var Scheduled_Backup
22
+ */
23
+ protected $schedule;
24
+
25
+ public function __construct( Scheduled_Backup $schedule ) {
26
+ $this->set_schedule( $schedule );
27
+ }
28
+
29
+ /**
30
+ * Used to determine if the service is in use or not
31
+ *
32
+ * @return boolean
33
+ */
34
+ abstract public function is_service_active();
35
+
36
+ /**
37
+ * The form to output as part of the schedule settings
38
+ *
39
+ * If you don't want a whole form return ''; here and use @field instead
40
+ *
41
+ * @return string The raw HTML for the form you want to output
42
+ */
43
+ abstract public function form();
44
+
45
+ /**
46
+ * The field to output as part of the schedule settings
47
+ *
48
+ * If you don't want a field return ''; here and use @form instead
49
+ *
50
+ * @return string The raw HTML for the field you want to output
51
+ */
52
+ abstract public function field();
53
+
54
+ /**
55
+ * Help text that should be output in the Constants help tab
56
+ *
57
+ * @return string The raw HTML for the Constant help text you want to output
58
+ */
59
+ public static function constant() {}
60
+
61
+ /**
62
+ * Validate and sanitize data before it's saved.
63
+ *
64
+ * @param array &$new_data An array or data from $_GET, passed by reference so it can be modified,
65
+ * @param array $old_data The old data thats going to be overwritten
66
+ * @return array $error Array of validation errors e.g. return array( 'email' => 'not valid' );
67
+ */
68
+ abstract public function update( &$new_data, $old_data );
69
+
70
+ /**
71
+ * The string to be output as part of the schedule sentence
72
+ *
73
+ * @return string
74
+ */
75
+ abstract public function display();
76
+
77
+ /**
78
+ * Receives actions from the backup
79
+ *
80
+ * This is where the service should do it's thing
81
+ *
82
+ * @see Backup::do_action for a list of the actions
83
+ */
84
+ abstract public function action( $action, Backup $backup );
85
+
86
+ public function get_slug() {
87
+ return strtolower( sanitize_title_with_dashes( $this->name ) );
88
+ }
89
+
90
+ /**
91
+ * Utility for getting a formated html input name attribute
92
+ *
93
+ * @param string $name The name of the field
94
+ * @return string The formated name
95
+ */
96
+ protected function get_field_name( $name ) {
97
+ return esc_attr( get_class( $this ) . '[' . $name . ']' );
98
+ }
99
+
100
+ /**
101
+ * Get the value of a field
102
+ *
103
+ * @param string $name The name of the field
104
+ * @param string $esc The escaping function that should be used
105
+ * @return string
106
+ */
107
+ protected function get_field_value( $name, $esc = 'esc_attr' ) {
108
+
109
+ if ( $name && $this->schedule->get_service_options( get_class( $this ), $name ) ) {
110
+ return $esc( $this->schedule->get_service_options( get_class( $this ), $name ) );
111
+ }
112
+
113
+ return '';
114
+
115
+ }
116
+
117
+ /**
118
+ * Save the settings for this service
119
+ *
120
+ * @return null|array returns null on success, array of errors on failure
121
+ */
122
+ public function save() {
123
+
124
+ $classname = get_class( $this );
125
+
126
+ $old_data = $this->schedule->get_service_options( $classname );
127
+
128
+ $new_data = isset( $_POST[$classname] ) ? $_POST[$classname] : array();
129
+
130
+ $errors = $this->update( $new_data, $old_data );
131
+
132
+ if ( $errors && $errors = array_flip( $errors ) ) {
133
+
134
+ foreach ( $errors as $error => &$field ) {
135
+ $field = get_class( $this ) . '[' . $field . ']';
136
+ }
137
+
138
+ return array_flip( $errors );
139
+
140
+ }
141
+
142
+ // Only overwrite settings if they changed
143
+ if ( ! empty( $new_data ) ) {
144
+ $this->schedule->set_service_options( $classname, $new_data );
145
+ }
146
+
147
+ return array();
148
+
149
+ }
150
+
151
+ /**
152
+ * Set the current schedule object
153
+ *
154
+ * @param Scheduled_Backup $schedule An instantiated schedule object
155
+ */
156
+ public function set_schedule( Scheduled_Backup $schedule ) {
157
+ $this->schedule = $schedule;
158
+ }
159
+
160
+ /**
161
+ * Gets the settings for a similar destination from the existing schedules
162
+ * so that we can copy them into the form to avoid having to type them again
163
+ *
164
+ * @return array
165
+ */
166
+ protected function fetch_destination_settings() {
167
+
168
+ $service = get_class( $this );
169
+
170
+ $schedules_obj = Schedules::get_instance();
171
+
172
+ $schedules = $schedules_obj->get_schedules();
173
+
174
+ foreach ( $schedules as $schedule ) {
175
+
176
+ if ( $schedule->get_id() != $this->schedule->get_id() ) {
177
+
178
+ $options = $schedule->get_service_options( $service );
179
+
180
+ if ( ! empty( $options ) ) {
181
+ return $options;
182
+ }
183
+
184
+ }
185
+
186
+ }
187
+
188
+ return array();
189
+
190
+ }
191
+
192
+ /**
193
+ * @return boolean
194
+ */
195
+ public function has_form() {
196
+
197
+ ob_start();
198
+
199
+ $this->form();
200
+
201
+ return (bool) ob_get_clean();
202
+
203
+ }
204
+
205
+ /**
206
+ * Handles passing service specific data to Intercom
207
+ */
208
+ public static function intercom_data() {}
209
+
210
+ public static function intercom_data_html() {}
211
+
212
+ }
classes/class-services.php CHANGED
@@ -1,215 +1,18 @@
1
  <?php
2
 
3
- /**
4
- * An abstract service class, individual services should
5
- * extend this class
6
- */
7
- abstract class HMBKP_Service {
8
-
9
- /**
10
- * Human readable name for this service
11
- * @var string
12
- */
13
- public $name;
14
-
15
- /**
16
- * The instance HMBKP_Backup_Schedule that this service is
17
- * is currently working with
18
- *
19
- * @var HMBKP_Scheduled_Backup
20
- */
21
- protected $schedule;
22
-
23
- public function __construct( $schedule ) {
24
-
25
- $this->set_schedule( $schedule );
26
- }
27
-
28
- /**
29
- * Used to determine if the service is in use or not
30
- */
31
- abstract public function is_service_active();
32
-
33
- /**
34
- * The form to output as part of the schedule settings
35
- *
36
- * If you don't want a whole form return ''; here and use @field instead
37
- */
38
- abstract public function form();
39
-
40
- /**
41
- * The field to output as part of the schedule settings
42
- *
43
- * If you don't want a field return ''; here and use @form instead
44
- */
45
- abstract public function field();
46
-
47
- /**
48
- * Help text that should be output in the Constants help tab
49
- */
50
- public static function constant() {}
51
-
52
- /**
53
- * Validate and sanitize data before it's saved.
54
- *
55
- * @param array &$new_data An array or data from $_GET, passed by reference so it can be modified,
56
- * @param array $old_data The old data thats going to be overwritten
57
- * @return array $error Array of validation errors e.g. return array( 'email' => 'not valid' );
58
- */
59
- abstract public function update( &$new_data, $old_data );
60
-
61
- /**
62
- * The string to be output as part of the schedule sentence
63
- *
64
- * @return string
65
- */
66
- abstract public function display();
67
-
68
- /**
69
- * Receives actions from the backup
70
- *
71
- * This is where the service should do it's thing
72
- *
73
- * @see HM_Backup::do_action for a list of the actions
74
- */
75
- abstract public function action( $action );
76
-
77
- public function get_slug() {
78
- return strtolower( sanitize_title_with_dashes( $this->name ) );
79
- }
80
-
81
- /**
82
- * Utility for getting a formated html input name attribute
83
- *
84
- * @param string $name The name of the field
85
- * @return string The formated name
86
- */
87
- protected function get_field_name( $name ) {
88
- return esc_attr( get_class( $this ) . '[' . $name . ']' );
89
- }
90
-
91
- /**
92
- * Get the value of a field
93
- *
94
- * @param string $name The name of the field
95
- * @param string $esc The field value
96
- * @return string
97
- */
98
- protected function get_field_value( $name, $esc = 'esc_attr' ) {
99
-
100
- if ( $this->schedule->get_service_options( get_class( $this ), $name ) )
101
- return $esc( $this->schedule->get_service_options( get_class( $this ), $name ) );
102
-
103
- return '';
104
-
105
- }
106
-
107
- /**
108
- * Save the settings for this service
109
- *
110
- * @return null|array returns null on success, array of errors on failure
111
- */
112
- public function save() {
113
-
114
- $classname = get_class( $this );
115
-
116
- $old_data = $this->schedule->get_service_options( $classname );
117
-
118
- $new_data = isset( $_POST[$classname] ) ? $_POST[$classname] : array();
119
-
120
- $errors = $this->update( $new_data, $old_data );
121
-
122
- if ( $errors && $errors = array_flip( $errors ) ) {
123
-
124
- foreach ( $errors as $error => &$field ) {
125
- $field = get_class( $this ) . '[' . $field . ']';
126
- }
127
-
128
- return array_flip( $errors );
129
-
130
- }
131
-
132
- // Only overwrite settings if they changed
133
- if ( ! empty( $new_data ) )
134
- $this->schedule->set_service_options( $classname, $new_data );
135
-
136
- return array();
137
-
138
- }
139
-
140
- /**
141
- * Set the current schedule object
142
- *
143
- * @param HMBKP_Scheduled_Backup $schedule An instantiated schedule object
144
- */
145
- public function set_schedule( HMBKP_Scheduled_Backup $schedule ) {
146
- $this->schedule = $schedule;
147
- }
148
-
149
- /**
150
- * Gets the settings for a similar destination from the existing schedules
151
- * so that we can copy them into the form to avoid having to type them again
152
- */
153
- protected function fetch_destination_settings() {
154
-
155
- $service = get_class( $this );
156
-
157
- $schedules_obj = HMBKP_Schedules::get_instance();
158
-
159
- $schedules = $schedules_obj->get_schedules();
160
-
161
- foreach ( $schedules as $schedule ) {
162
-
163
- if ( $schedule->get_id() != $this->schedule->get_id() ) {
164
-
165
- $options = $schedule->get_service_options( $service );
166
-
167
- if ( ! empty( $options ) )
168
- return $options;
169
-
170
- }
171
-
172
- }
173
-
174
- return array();
175
-
176
- }
177
-
178
- public function has_form() {
179
-
180
- ob_start();
181
-
182
- $this->form();
183
-
184
- $form = ob_get_clean();
185
-
186
- if ( $form )
187
- return true;
188
-
189
- return false;
190
-
191
- }
192
-
193
- /**
194
- * Handles passing service specific data to Intercom
195
- */
196
- public static function intercom_data() {}
197
-
198
- public static function intercom_data_html() {}
199
-
200
- }
201
 
202
  /**
203
  * A singleton to handle the registering, de-registering
204
  * and storage of services
205
  */
206
- class HMBKP_Services {
207
 
208
  /**
209
  * Store the current instance
210
  *
211
  * @access private
212
- * @var object HMBKP_Services
213
  * @static
214
  */
215
  private static $instance;
@@ -229,20 +32,19 @@ class HMBKP_Services {
229
  * The current schedule object
230
  *
231
  * @access private
232
- * @var object HMBKP_Scheduled_Backup
233
  */
234
  private $schedule;
235
 
236
  /**
237
  * Get the current instance
238
  *
239
- * @access public
240
  * @static
241
  */
242
  public static function instance() {
243
 
244
  if ( ! isset( self::$instance ) )
245
- self::$instance = new HMBKP_Services;
246
 
247
  return self::$instance;
248
 
@@ -251,13 +53,14 @@ class HMBKP_Services {
251
  /**
252
  * Get the array of registered services
253
  *
254
- * @param HMBKP_Scheduled_Backup $schedule
255
- * @return HMBKP_SERVICE[]
256
  */
257
- public static function get_services( HMBKP_Scheduled_Backup $schedule = null ) {
258
 
259
- if ( is_null( $schedule ) )
260
  return self::instance()->services;
 
261
 
262
  self::instance()->schedule = $schedule;
263
 
@@ -274,8 +77,9 @@ class HMBKP_Services {
274
  */
275
  public static function register( $filepath, $classname ) {
276
 
277
- if ( ! file_exists( $filepath ) )
278
- return new WP_Error( 'hmbkp_invalid_path_error', sprintf( __( 'Argument 1 for %s must be a valid filepath', 'backupwordpress' ), __METHOD__ ) );
 
279
 
280
  self::instance()->services[ $filepath ] = $classname;
281
 
@@ -289,8 +93,9 @@ class HMBKP_Services {
289
  */
290
  public static function unregister( $filepath ) {
291
 
292
- if ( ! isset( self::instance()->services[ $filepath ] ) )
293
- return new WP_Error( 'hmbkp_unrecognized_service_error', sprintf( __( 'Argument 1 for %s must be a registered service', 'backupwordpress' ), __METHOD__ ) );
 
294
 
295
  unset( self::instance()->services[ $filepath ] );
296
 
@@ -306,11 +111,12 @@ class HMBKP_Services {
306
  */
307
  private static function instantiate( $classname ) {
308
 
309
- if ( ! class_exists( $classname ) )
310
- return new WP_Error( 'hmbkp_invalid_type_error', sprintf( __( 'Argument 1 for %s must be a valid class', 'backupwordpress' ) ), __METHOD__ );
 
311
 
312
  /**
313
- * @var HMBKP_Service
314
  */
315
  $class = new $classname( self::instance()->schedule );
316
 
1
  <?php
2
 
3
+ namespace HM\BackUpWordPress;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  /**
6
  * A singleton to handle the registering, de-registering
7
  * and storage of services
8
  */
9
+ class Services {
10
 
11
  /**
12
  * Store the current instance
13
  *
14
  * @access private
15
+ * @var object Services
16
  * @static
17
  */
18
  private static $instance;
32
  * The current schedule object
33
  *
34
  * @access private
35
+ * @var object Scheduled_Backup
36
  */
37
  private $schedule;
38
 
39
  /**
40
  * Get the current instance
41
  *
 
42
  * @static
43
  */
44
  public static function instance() {
45
 
46
  if ( ! isset( self::$instance ) )
47
+ self::$instance = new Services;
48
 
49
  return self::$instance;
50
 
53
  /**
54
  * Get the array of registered services
55
  *
56
+ * @param Scheduled_Backup $schedule
57
+ * @return Service[]
58
  */
59
+ public static function get_services( Scheduled_Backup $schedule = null ) {
60
 
61
+ if ( is_null( $schedule ) ) {
62
  return self::instance()->services;
63
+ }
64
 
65
  self::instance()->schedule = $schedule;
66
 
77
  */
78
  public static function register( $filepath, $classname ) {
79
 
80
+ if ( ! file_exists( $filepath ) ) {
81
+ return new \WP_Error( 'hmbkp_invalid_path_error', sprintf( __( 'Argument 1 for %s must be a valid filepath', 'backupwordpress' ), __METHOD__ ) );
82
+ }
83
 
84
  self::instance()->services[ $filepath ] = $classname;
85
 
93
  */
94
  public static function unregister( $filepath ) {
95
 
96
+ if ( ! isset( self::instance()->services[ $filepath ] ) ) {
97
+ return new \WP_Error( 'hmbkp_unrecognized_service_error', sprintf( __( 'Argument 1 for %s must be a registered service', 'backupwordpress' ), __METHOD__ ) );
98
+ }
99
 
100
  unset( self::instance()->services[ $filepath ] );
101
 
111
  */
112
  private static function instantiate( $classname ) {
113
 
114
+ if ( ! class_exists( $classname ) ) {
115
+ return new \WP_Error( 'hmbkp_invalid_type_error', sprintf( __( 'Argument 1 for %s must be a valid class', 'backupwordpress' ) ), __METHOD__ );
116
+ }
117
 
118
  /**
119
+ * @var Service
120
  */
121
  $class = new $classname( self::instance()->schedule );
122
 
classes/class-setup.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
 
3
- defined( 'ABSPATH' ) or exit;
4
 
5
  /**
6
  * Class BackUpWordPress_Setup
7
  */
8
- class BackUpWordPress_Setup {
9
 
10
  /**
11
  * Defines the minimum version of WordPress required by BWP.
@@ -51,28 +51,15 @@ class BackUpWordPress_Setup {
51
  return;
52
  }
53
 
54
- // Determine if we need to do any cleanup
55
- if ( ! class_exists( 'HMBKP_Schedules' ) ) {
56
- return;
57
- }
58
 
59
- $schedules = HMBKP_Schedules::get_instance();
60
 
61
- if ( empty( $schedules ) ) {
62
- return;
63
  }
64
 
65
- // Clear schedule crons
66
- foreach ( $schedules->get_schedules() as $schedule ) {
67
- $schedule->unschedule();
68
- }
69
-
70
- // Opt them out of support
71
- delete_option( 'hmbkp_enable_support' );
72
-
73
- // Remove the directory filesize cache
74
- delete_transient( 'hmbkp_directory_filesizes' );
75
-
76
  }
77
 
78
  /**
@@ -139,7 +126,7 @@ class BackUpWordPress_Setup {
139
  */
140
  public static function display_admin_notices() {
141
 
142
- echo '<div class="error"><p>' . self::get_notice_message() . '</p></div>';
143
 
144
  }
145
 
1
  <?php
2
 
3
+ namespace HM\BackUpWordPress;
4
 
5
  /**
6
  * Class BackUpWordPress_Setup
7
  */
8
+ class Setup {
9
 
10
  /**
11
  * Defines the minimum version of WordPress required by BWP.
51
  return;
52
  }
53
 
54
+ // Delete Cron schedules.
55
+ global $wpdb;
 
 
56
 
57
+ $schedules = $wpdb->get_col( $wpdb->prepare( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE %s", 'hmbkp_schedule_%' ) );
58
 
59
+ foreach ( array_map( function( $item ){ return ltrim( $item, 'hmbkp_schedule_' ); }, $schedules ) as $item ) {
60
+ wp_clear_scheduled_hook( 'hmbkp_schedule_hook', array( 'id' => $item ) );
61
  }
62
 
 
 
 
 
 
 
 
 
 
 
 
63
  }
64
 
65
  /**
126
  */
127
  public static function display_admin_notices() {
128
 
129
+ echo '<div class="error"><p>' . esc_html( self::get_notice_message() ) . '</p></div>';
130
 
131
  }
132
 
classes/{class-webhooks.php → class-webhook-service.php} RENAMED
@@ -1,11 +1,13 @@
1
  <?php
2
 
 
 
3
  /**
4
  * Webhook notifications for backups
5
  *
6
- * @extends HMBKP_Service
7
  */
8
- abstract class HMBKP_Webhooks_Service extends HMBKP_Service {
9
 
10
  /**
11
  * Human readable name for this service
@@ -13,10 +15,6 @@ abstract class HMBKP_Webhooks_Service extends HMBKP_Service {
13
  */
14
  public $name = 'Webhook';
15
 
16
- public function __construct( $schedule ) {
17
- parent::__construct( $schedule );
18
- }
19
-
20
  /**
21
  * @return string
22
  */
@@ -30,30 +28,33 @@ abstract class HMBKP_Webhooks_Service extends HMBKP_Service {
30
  /**
31
  * Fire the webhook notification on the hmbkp_backup_complete
32
  *
33
- * @see HM_Backup::do_action
34
  * @param string $action The action received from the backup
35
  * @return void
36
  */
37
- public function action( $action ) {
38
 
39
- if ( 'hmbkp_backup_complete' !== $action || ! $this->is_service_active() )
40
  return;
 
41
 
42
  $webhook_url = $this->get_url();
43
- $file = $this->schedule->get_archive_filepath();
44
  $download = add_query_arg( 'hmbkp_download', base64_encode( $file ), HMBKP_ADMIN_URL );
45
  $domain = parse_url( home_url(), PHP_URL_HOST ) . parse_url( home_url(), PHP_URL_PATH );
46
 
47
  // The backup failed, send a message saying as much
48
- if ( ! file_exists( $file ) && ( $errors = array_merge( $this->schedule->get_errors(), $this->schedule->get_warnings() ) ) ) {
49
 
50
  $error_message = '';
51
 
52
- foreach ( $errors as $error_set )
53
  $error_message .= implode( "\n - ", $error_set );
 
54
 
55
- if ( $error_message )
56
  $error_message = ' - ' . $error_message;
 
57
 
58
  $subject = sprintf( __( 'Backup of %s Failed', 'backupwordpress' ), $domain );
59
 
@@ -98,12 +99,14 @@ abstract class HMBKP_Webhooks_Service extends HMBKP_Service {
98
 
99
  $ret = wp_remote_post( $webhook_url, $webhook_args );
100
 
101
- if ( is_wp_error( $ret ) )
102
- $this->schedule->error( 'Webhook', sprintf( __( 'Error: %s', 'backupwordpress' ), $ret->get_error_message() ) );
 
103
 
104
  }
105
 
106
  public static function intercom_data() { return array(); }
107
 
108
  public static function intercom_data_html() {}
 
109
  }
1
  <?php
2
 
3
+ namespace HM\BackUpWordPress;
4
+
5
  /**
6
  * Webhook notifications for backups
7
  *
8
+ * @extends Service
9
  */
10
+ abstract class Webhook_Service extends Service {
11
 
12
  /**
13
  * Human readable name for this service
15
  */
16
  public $name = 'Webhook';
17
 
 
 
 
 
18
  /**
19
  * @return string
20
  */
28
  /**
29
  * Fire the webhook notification on the hmbkp_backup_complete
30
  *
31
+ * @see Backup::do_action
32
  * @param string $action The action received from the backup
33
  * @return void
34
  */
35
+ public function action( $action, Backup $backup ) {
36
 
37
+ if ( 'hmbkp_backup_complete' !== $action || ! $this->is_service_active() ) {
38
  return;
39
+ }
40
 
41
  $webhook_url = $this->get_url();
42
+ $file = $backup->get_archive_filepath();
43
  $download = add_query_arg( 'hmbkp_download', base64_encode( $file ), HMBKP_ADMIN_URL );
44
  $domain = parse_url( home_url(), PHP_URL_HOST ) . parse_url( home_url(), PHP_URL_PATH );
45
 
46
  // The backup failed, send a message saying as much
47
+ if ( ! file_exists( $file ) && ( $errors = array_merge( $backup->get_errors(), $backup->get_warnings() ) ) ) {
48
 
49
  $error_message = '';
50
 
51
+ foreach ( $errors as $error_set ) {
52
  $error_message .= implode( "\n - ", $error_set );
53
+ }
54
 
55
+ if ( $error_message ) {
56
  $error_message = ' - ' . $error_message;
57
+ }
58
 
59
  $subject = sprintf( __( 'Backup of %s Failed', 'backupwordpress' ), $domain );
60
 
99
 
100
  $ret = wp_remote_post( $webhook_url, $webhook_args );
101
 
102
+ if ( is_wp_error( $ret ) ) {
103
+ $backup->error( 'Webhook', sprintf( __( 'Error: %s', 'backupwordpress' ), $ret->get_error_message() ) );
104
+ }
105
 
106
  }
107
 
108
  public static function intercom_data() { return array(); }
109
 
110
  public static function intercom_data_html() {}
111
+
112
  }
classes/{class-webhook-wpremote.php → class-wpremote-webhook-service.php} RENAMED
@@ -1,17 +1,19 @@
1
  <?php
2
 
 
 
3
  /**
4
  * Webhook notifications for backups on WPRemote
5
  *
6
- * @extends HMBKP_Service
7
  */
8
- class HMBKP_Webhook_WPRemote_Service extends HMBKP_Webhooks_Service {
9
 
10
  /**
11
  * Human readable name for this service
12
  * @var string
13
  */
14
- public $name = 'WPRemote Webhook';
15
 
16
  private $wpremote_webhook_url = 'http://wpremote.com/api/json/backupwordpress/webhook';
17
 
@@ -54,7 +56,6 @@ class HMBKP_Webhook_WPRemote_Service extends HMBKP_Webhooks_Service {
54
  * @return string
55
  */
56
  protected function get_url() {
57
-
58
  return ( defined( 'WPRP_PLUGIN_SLUG' ) && get_option( 'wpr_api_key' ) ) ? $this->wpremote_webhook_url : false;
59
  }
60
 
@@ -62,11 +63,10 @@ class HMBKP_Webhook_WPRemote_Service extends HMBKP_Webhooks_Service {
62
  * @return string
63
  */
64
  protected function get_secret_key() {
65
-
66
  return get_option( 'wpr_api_key' );
67
  }
68
 
69
  }
70
 
71
  // Register the service
72
- HMBKP_Services::register( __FILE__, 'HMBKP_Webhook_WPRemote_Service' );
1
  <?php
2
 
3
+ namespace HM\BackUpWordPress;
4
+
5
  /**
6
  * Webhook notifications for backups on WPRemote
7
  *
8
+ * @extends Service
9
  */
10
+ class WPRemote_Webhook_Service extends Webhook_Service {
11
 
12
  /**
13
  * Human readable name for this service
14
  * @var string
15
  */
16
+ public $name = 'WP Remote Webhook';
17
 
18
  private $wpremote_webhook_url = 'http://wpremote.com/api/json/backupwordpress/webhook';
19
 
56
  * @return string
57
  */
58
  protected function get_url() {
 
59
  return ( defined( 'WPRP_PLUGIN_SLUG' ) && get_option( 'wpr_api_key' ) ) ? $this->wpremote_webhook_url : false;
60
  }
61
 
63
  * @return string
64
  */
65
  protected function get_secret_key() {
 
66
  return get_option( 'wpr_api_key' );
67
  }
68
 
69
  }
70
 
71
  // Register the service
72
+ Services::register( __FILE__, 'HM\BackUpWordPress\WPRemote_Webhook_Service' );
functions/core.php CHANGED
@@ -1,5 +1,15 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
 
3
  /**
4
  * Handles anything that needs to be
5
  * done when the plugin is updated
@@ -53,7 +63,7 @@ function hmbkp_update() {
53
  /**
54
  * Setup a backwards compatible schedule
55
  */
56
- $legacy_schedule = new HMBKP_Scheduled_Backup( 'backup' );
57
 
58
  // Backup type
59
  if ( ( defined( 'HMBKP_FILES_ONLY' ) && HMBKP_FILES_ONLY ) || get_option( 'hmbkp_files_only' ) ) {
@@ -105,7 +115,7 @@ function hmbkp_update() {
105
  }
106
 
107
  // Set the archive filename to what it used to be
108
- $legacy_schedule->set_archive_filename( implode( '-', array( get_bloginfo( 'name' ), 'backup', date( 'Y-m-d-H-i-s', current_time( 'timestamp' ) ) ) ) . '.zip' );
109
 
110
  $legacy_schedule->save();
111
 
@@ -119,7 +129,7 @@ function hmbkp_update() {
119
  // Update from 2.2.4
120
  if ( get_option( 'hmbkp_plugin_version' ) && version_compare( '2.2.5', get_option( 'hmbkp_plugin_version' ), '>' ) ) {
121
 
122
- $schedules = HMBKP_Schedules::get_instance();
123
 
124
  // Loop through all schedules and re-set the reccurrence to include hmbkp_
125
  foreach ( $schedules->get_schedules() as $schedule ) {
@@ -154,17 +164,17 @@ function hmbkp_update() {
154
  }
155
 
156
  // Every update
157
- if ( get_option( 'hmbkp_plugin_version' ) && version_compare( BackUpWordPress_Plugin::PLUGIN_VERSION, get_option( 'hmbkp_plugin_version' ), '>' ) ) {
158
 
159
- BackUpWordPress_Setup::deactivate();
160
 
161
- HMBKP_Path::get_instance()->protect_path( 'reset' );
162
 
163
  }
164
 
165
  // Update the stored version
166
- if ( get_option( 'hmbkp_plugin_version' ) !== BackUpWordPress_Plugin::PLUGIN_VERSION ) {
167
- update_option( 'hmbkp_plugin_version', BackUpWordPress_Plugin::PLUGIN_VERSION );
168
  }
169
 
170
  }
@@ -174,16 +184,17 @@ function hmbkp_update() {
174
  */
175
  function hmbkp_setup_default_schedules() {
176
 
177
- $schedules = HMBKP_Schedules::get_instance();
178
 
179
- if ( $schedules->get_schedules() )
180
  return;
 
181
 
182
  /**
183
  * Schedule a database backup daily and store backups
184
  * for the last 2 weeks
185
  */
186
- $database_daily = new HMBKP_Scheduled_Backup( (string) time() );
187
  $database_daily->set_type( 'database' );
188
  $database_daily->set_schedule_start_time( hmbkp_determine_start_time( 'hmbkp_daily', array( 'hours' => '23', 'minutes' => '0' ) ) );
189
  $database_daily->set_reoccurrence( 'hmbkp_daily' );
@@ -194,7 +205,7 @@ function hmbkp_setup_default_schedules() {
194
  * Schedule a complete backup to run weekly and store backups for
195
  * the last 3 months
196
  */
197
- $complete_weekly = new HMBKP_Scheduled_Backup( (string) ( time() + 1 ) );
198
  $complete_weekly->set_type( 'complete' );
199
  $complete_weekly->set_schedule_start_time( hmbkp_determine_start_time( 'hmbkp_weekly', array( 'day_of_week' => 'sunday', 'hours' => '3', 'minutes' => '0' ) ) );
200
  $complete_weekly->set_reoccurrence( 'hmbkp_weekly' );
@@ -203,11 +214,9 @@ function hmbkp_setup_default_schedules() {
203
 
204
  $schedules->refresh_schedules();
205
 
206
- function hmbkp_default_schedules_setup_warning() {
207
  echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has setup your default schedules.', 'backupwordpress' ) . '</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.', 'backupwordpress' ) . '</p></div>';
208
- }
209
-
210
- add_action( 'admin_notices', 'hmbkp_default_schedules_setup_warning' );
211
 
212
  }
213
 
@@ -243,7 +252,7 @@ add_filter( 'cron_schedules', 'hmbkp_cron_schedules' );
243
  */
244
  function hmbkp_rmdirtree( $dir ) {
245
 
246
- if ( false !== strpos( HM_Backup::get_home_path(), $dir ) )
247
  return new WP_Error( 'hmbkp_invalid_action_error', sprintf( __( 'You can only delete directories inside your WordPress installation', 'backupwordpress' ) ) );
248
 
249
  if ( is_file( $dir ) )
@@ -281,7 +290,7 @@ function hmbkp_possible() {
281
  return false;
282
  }
283
 
284
- $test_backup = new HMBKP_Scheduled_Backup( 'test_backup' );
285
 
286
  if ( ! is_readable( $test_backup->get_root() ) ) {
287
  return false;
@@ -311,7 +320,7 @@ function hmbkp_get_max_attachment_size() {
311
  function hmbkp_is_path_accessible( $dir ) {
312
 
313
  // Path is inaccessible
314
- if ( strpos( $dir, HM_Backup::get_home_path() ) === false ) {
315
  return false;
316
  }
317
 
@@ -374,9 +383,7 @@ function hmbkp_determine_start_time( $type, $times = array() ) {
374
 
375
  $args = wp_parse_args( $times, $default_times );
376
 
377
- $schedule_start = '';
378
-
379
- $intervals = HMBKP_Scheduled_Backup::get_cron_schedules();
380
 
381
  // Allow the hours and minutes to be overwritten by a constant
382
  if ( defined( 'HMBKP_SCHEDULE_TIME' ) && HMBKP_SCHEDULE_TIME ) {
@@ -411,20 +418,21 @@ function hmbkp_determine_start_time( $type, $times = array() ) {
411
  $schedule_start = date( 'F', $args['now'] ) . ' ' . $args['day_of_month'] . ' ' . $hm;
412
 
413
  // If we've already gone past that day this month then we'll need to start next month
414
- if ( strtotime( $schedule_start, $args['now'] ) <= $args['now'] )
415
  $schedule_start = date( 'F', strtotime( '+ 1 month', $args['now'] ) ) . ' ' . $args['day_of_month'] . ' ' . $hm;
 
416
 
417
  // If that's still in the past then we'll need to jump to next year
418
- if ( strtotime( $schedule_start, $args['now'] ) <= $args['now'] )
419
  $schedule_start = date( 'F', strtotime( '+ 1 month', $args['now'] ) ) . ' ' . $args['day_of_month'] . ' ' . date( 'Y', strtotime( '+ 1 year', $args['now'] ) ) . ' ' . $hm;
 
420
 
421
  break;
 
422
  default :
423
 
424
  return 0;
425
 
426
- break;
427
-
428
  }
429
 
430
  $timestamp = strtotime( $schedule_start, $args['now'] );
1
  <?php
2
 
3
+ /**
4
+ * Returns the backup path
5
+ *
6
+ * @see Path
7
+ * @todo remove the need for this
8
+ */
9
+ function hmbkp_path() {
10
+ return HM\BackUpWordPress\Path::get_instance()->get_path();
11
+ }
12
+
13
  /**
14
  * Handles anything that needs to be
15
  * done when the plugin is updated
63
  /**
64
  * Setup a backwards compatible schedule
65
  */
66
+ $legacy_schedule = new HM\BackUpWordPress\Scheduled_Backup( 'backup' );
67
 
68
  // Backup type
69
  if ( ( defined( 'HMBKP_FILES_ONLY' ) && HMBKP_FILES_ONLY ) || get_option( 'hmbkp_files_only' ) ) {
115
  }
116
 
117
  // Set the archive filename to what it used to be
118
+ $legacy_schedule->backup->set_archive_filename( implode( '-', array( get_bloginfo( 'name' ), 'backup', current_time( 'Y-m-d-H-i-s' ) ) ) . '.zip' );
119
 
120
  $legacy_schedule->save();
121
 
129
  // Update from 2.2.4
130
  if ( get_option( 'hmbkp_plugin_version' ) && version_compare( '2.2.5', get_option( 'hmbkp_plugin_version' ), '>' ) ) {
131
 
132
+ $schedules = HM\BackUpWordPress\Schedules::get_instance();
133
 
134
  // Loop through all schedules and re-set the reccurrence to include hmbkp_
135
  foreach ( $schedules->get_schedules() as $schedule ) {
164
  }
165
 
166
  // Every update
167
+ if ( get_option( 'hmbkp_plugin_version' ) && version_compare( HM\BackUpWordPress\Plugin::PLUGIN_VERSION, get_option( 'hmbkp_plugin_version' ), '>' ) ) {
168
 
169
+ HM\BackUpWordPress\Setup::deactivate();
170
 
171
+ HM\BackUpWordPress\Path::get_instance()->protect_path( 'reset' );
172
 
173
  }
174
 
175
  // Update the stored version
176
+ if ( get_option( 'hmbkp_plugin_version' ) !== HM\BackUpWordPress\Plugin::PLUGIN_VERSION ) {
177
+ update_option( 'hmbkp_plugin_version', HM\BackUpWordPress\Plugin::PLUGIN_VERSION );
178
  }
179
 
180
  }
184
  */
185
  function hmbkp_setup_default_schedules() {
186
 
187
+ $schedules = HM\BackUpWordPress\Schedules::get_instance();
188
 
189
+ if ( $schedules->get_schedules() ) {
190
  return;
191
+ }
192
 
193
  /**
194
  * Schedule a database backup daily and store backups
195
  * for the last 2 weeks
196
  */
197
+ $database_daily = new HM\BackUpWordPress\Scheduled_Backup( (string) time() );
198
  $database_daily->set_type( 'database' );
199
  $database_daily->set_schedule_start_time( hmbkp_determine_start_time( 'hmbkp_daily', array( 'hours' => '23', 'minutes' => '0' ) ) );
200
  $database_daily->set_reoccurrence( 'hmbkp_daily' );
205
  * Schedule a complete backup to run weekly and store backups for
206
  * the last 3 months
207
  */
208
+ $complete_weekly = new HM\BackUpWordPress\Scheduled_Backup( (string) ( time() + 1 ) );
209
  $complete_weekly->set_type( 'complete' );
210
  $complete_weekly->set_schedule_start_time( hmbkp_determine_start_time( 'hmbkp_weekly', array( 'day_of_week' => 'sunday', 'hours' => '3', 'minutes' => '0' ) ) );
211
  $complete_weekly->set_reoccurrence( 'hmbkp_weekly' );
214
 
215
  $schedules->refresh_schedules();
216
 
217
+ add_action( 'admin_notices', function() {
218
  echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has setup your default schedules.', 'backupwordpress' ) . '</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.', 'backupwordpress' ) . '</p></div>';
219
+ } );
 
 
220
 
221
  }
222
 
252
  */
253
  function hmbkp_rmdirtree( $dir ) {
254
 
255
+ if ( false !== strpos( HM\BackUpWordPress\Backup::get_home_path(), $dir ) )
256
  return new WP_Error( 'hmbkp_invalid_action_error', sprintf( __( 'You can only delete directories inside your WordPress installation', 'backupwordpress' ) ) );
257
 
258
  if ( is_file( $dir ) )
290
  return false;
291
  }
292
 
293
+ $test_backup = new HM\BackUpWordPress\Backup();
294
 
295
  if ( ! is_readable( $test_backup->get_root() ) ) {
296
  return false;
320
  function hmbkp_is_path_accessible( $dir ) {
321
 
322
  // Path is inaccessible
323
+ if ( strpos( $dir, HM\BackUpWordPress\Backup::get_home_path() ) === false ) {
324
  return false;
325
  }
326
 
383
 
384
  $args = wp_parse_args( $times, $default_times );
385
 
386
+ $intervals = HM\BackUpWordPress\Scheduled_Backup::get_cron_schedules();
 
 
387
 
388
  // Allow the hours and minutes to be overwritten by a constant
389
  if ( defined( 'HMBKP_SCHEDULE_TIME' ) && HMBKP_SCHEDULE_TIME ) {
418
  $schedule_start = date( 'F', $args['now'] ) . ' ' . $args['day_of_month'] . ' ' . $hm;
419
 
420
  // If we've already gone past that day this month then we'll need to start next month
421
+ if ( strtotime( $schedule_start, $args['now'] ) <= $args['now'] ) {
422
  $schedule_start = date( 'F', strtotime( '+ 1 month', $args['now'] ) ) . ' ' . $args['day_of_month'] . ' ' . $hm;
423
+ }
424
 
425
  // If that's still in the past then we'll need to jump to next year
426
+ if ( strtotime( $schedule_start, $args['now'] ) <= $args['now'] ) {
427
  $schedule_start = date( 'F', strtotime( '+ 1 month', $args['now'] ) ) . ' ' . $args['day_of_month'] . ' ' . date( 'Y', strtotime( '+ 1 year', $args['now'] ) ) . ' ' . $hm;
428
+ }
429
 
430
  break;
431
+
432
  default :
433
 
434
  return 0;
435
 
 
 
436
  }
437
 
438
  $timestamp = strtotime( $schedule_start, $args['now'] );
functions/interface.php CHANGED
@@ -4,9 +4,9 @@
4
  * Displays a row in the manage backups table
5
  *
6
  * @param string $file
7
- * @param HMBKP_Scheduled_Backup $schedule
8
  */
9
- function hmbkp_get_backup_row( $file, HMBKP_Scheduled_Backup $schedule ) {
10
 
11
  $encoded_file = urlencode( base64_encode( $file ) );
12
  $offset = get_option( 'gmt_offset' ) * 3600;
@@ -53,7 +53,7 @@ function hmbkp_admin_notices() {
53
  return;
54
  }
55
 
56
- $notices = HMBKP_Notices::get_instance()->get_notices();
57
 
58
  if ( empty( $notices ) ) {
59
  return;
@@ -78,6 +78,7 @@ function hmbkp_admin_notices() {
78
  </ul>
79
 
80
  </div>
 
81
  <?php endif; ?>
82
 
83
  <?php if ( ! empty( $notices['server_config'] ) ) : ?>
@@ -102,11 +103,11 @@ add_action( 'network_admin_notices', 'hmbkp_admin_notices' );
102
 
103
  function hmbkp_set_server_config_notices() {
104
 
105
- $notices = HMBKP_Notices::get_instance();
106
 
107
  $messages = array();
108
 
109
- if ( ! HM_Backup::is_shell_exec_available() ) {
110
  $php_user = '<PHP USER>';
111
  $php_group = '<PHP GROUP>';
112
  } else {
@@ -123,7 +124,7 @@ function hmbkp_set_server_config_notices() {
123
  $messages[] = sprintf( __( 'Your backups directory isn\'t writable, run %1$s or %2$s or set the permissions yourself.', 'backupwordpress' ), '<code>chown -R ' . esc_html( $php_user ) . ':' . esc_html( $php_group ) . ' ' . esc_html( hmbkp_path() ) . '</code>', '<code>chmod -R 777 ' . esc_html( hmbkp_path() ) . '</code>' );
124
  }
125
 
126
- if ( HM_Backup::is_safe_mode_active() ) {
127
  $messages[] = sprintf( __( '%1$s is running in %2$s, please contact your host and ask them to disable it. BackUpWordPress may not work correctly whilst %3$s is on.', 'backupwordpress' ), '<code>PHP</code>', sprintf( '<a href="%1$s">%2$s</a>', __( 'http://php.net/manual/en/features.safe-mode.php', 'backupwordpress' ), __( 'Safe Mode', 'backupwordpress' ) ), '<code>' . __( 'Safe Mode', 'backupwordpress' ) . '</code>' );
128
  }
129
 
@@ -151,7 +152,7 @@ function hmbkp_set_server_config_notices() {
151
  }
152
  }
153
 
154
- $test_backup = new HMBKP_Scheduled_Backup( 'test_backup' );
155
 
156
  if ( ! is_readable( $test_backup->get_root() ) ) {
157
  $messages[] = sprintf( __( 'Your site root path %s isn\'t readable.', 'backupwordpress' ), '<code>' . $test_backup->get_root() . '</code>' );
@@ -208,22 +209,26 @@ function hmbkp_backup_errors_message() {
208
  *
209
  * @access public
210
  * @param string $type
211
- * @param HMBKP_Scheduled_Backup $schedule (default: null)
212
  * @return string
213
  */
214
- function hmbkp_human_get_type( $type, HMBKP_Scheduled_Backup $schedule = null ) {
215
 
216
- if ( strpos( $type, 'complete' ) !== false )
217
  return __( 'Database and Files', 'backupwordpress' );
 
218
 
219
- if ( strpos( $type, 'file' ) !== false )
220
  return __( 'Files', 'backupwordpress' );
 
221
 
222
- if ( strpos( $type, 'database' ) !== false )
223
  return __( 'Database', 'backupwordpress' );
 
224
 
225
- if ( ! is_null( $schedule ) )
226
  return hmbkp_human_get_type( $schedule->get_type() );
 
227
 
228
  return __( 'Legacy', 'backupwordpress' );
229
 
@@ -233,10 +238,10 @@ function hmbkp_human_get_type( $type, HMBKP_Scheduled_Backup $schedule = null )
233
  * Display the row of actions for a schedule
234
  *
235
  * @access public
236
- * @param HMBKP_Scheduled_Backup $schedule
237
  * @return void
238
  */
239
- function hmbkp_schedule_status( HMBKP_Scheduled_Backup $schedule, $echo = true ) {
240
 
241
  ob_start(); ?>
242
 
@@ -262,8 +267,9 @@ function hmbkp_schedule_status( HMBKP_Scheduled_Backup $schedule, $echo = true )
262
  */
263
  function hmbkp_backup_errors() {
264
 
265
- if ( ! file_exists( hmbkp_path() . '/.backup_errors' ) )
266
  return '';
 
267
 
268
  return file_get_contents( hmbkp_path() . '/.backup_errors' );
269
 
@@ -276,8 +282,9 @@ function hmbkp_backup_errors() {
276
  */
277
  function hmbkp_backup_warnings() {
278
 
279
- if ( ! file_exists( hmbkp_path() . '/.backup_warnings' ) )
280
  return '';
 
281
 
282
  return file_get_contents( hmbkp_path() . '/.backup_warnings' );
283
 
@@ -290,8 +297,7 @@ function hmbkp_backups_number( $schedule ) {
290
  if ( 0 === $number ) {
291
  $output = sprintf( __( 'No backups completed', 'backupwordpress' ) );
292
  } else {
293
- $output = sprintf( _nx( 'One backup completed', '%1$s backups completed', $number, 'backups count', 'backupwordpress' ),
294
- number_format_i18n( $number ) );
295
  }
296
 
297
  echo apply_filters( 'hmbkp_backups_number', $output, $number );
@@ -339,9 +345,9 @@ function hmbkp_get_settings_url() {
339
  $url = admin_url( 'tools.php?page=' . HMBKP_PLUGIN_SLUG );
340
  }
341
 
342
- HMBKP_schedules::get_instance()->refresh_schedules();
343
 
344
- if ( ! empty( $_REQUEST['hmbkp_schedule_id'] ) && HMBKP_schedules::get_instance()->get_schedule( sanitize_text_field( $_REQUEST['hmbkp_schedule_id'] ) ) ) {
345
  $url = add_query_arg( 'hmbkp_schedule_id', sanitize_text_field( $_REQUEST['hmbkp_schedule_id'] ), $url );
346
  }
347
 
@@ -373,7 +379,6 @@ function hmbkp_add_settings_error( $error_message ){
373
  * @return mixed
374
  */
375
  function hmbkp_get_settings_errors() {
376
-
377
  return get_transient( 'hmbkp_settings_errors' );
378
  }
379
 
4
  * Displays a row in the manage backups table
5
  *
6
  * @param string $file
7
+ * @param HM\BackUpWordPress\Scheduled_Backup $schedule
8
  */
9
+ function hmbkp_get_backup_row( $file, HM\BackUpWordPress\Scheduled_Backup $schedule ) {
10
 
11
  $encoded_file = urlencode( base64_encode( $file ) );
12
  $offset = get_option( 'gmt_offset' ) * 3600;
53
  return;
54
  }
55
 
56
+ $notices = HM\BackUpWordPress\Notices::get_instance()->get_notices();
57
 
58
  if ( empty( $notices ) ) {
59
  return;
78
  </ul>
79
 
80
  </div>
81
+
82
  <?php endif; ?>
83
 
84
  <?php if ( ! empty( $notices['server_config'] ) ) : ?>
103
 
104
  function hmbkp_set_server_config_notices() {
105
 
106
+ $notices = HM\BackUpWordPress\Notices::get_instance();
107
 
108
  $messages = array();
109
 
110
+ if ( ! HM\BackUpWordPress\Backup::is_shell_exec_available() ) {
111
  $php_user = '<PHP USER>';
112
  $php_group = '<PHP GROUP>';
113
  } else {
124
  $messages[] = sprintf( __( 'Your backups directory isn\'t writable, run %1$s or %2$s or set the permissions yourself.', 'backupwordpress' ), '<code>chown -R ' . esc_html( $php_user ) . ':' . esc_html( $php_group ) . ' ' . esc_html( hmbkp_path() ) . '</code>', '<code>chmod -R 777 ' . esc_html( hmbkp_path() ) . '</code>' );
125
  }
126
 
127
+ if ( HM\BackUpWordPress\Backup::is_safe_mode_active() ) {
128
  $messages[] = sprintf( __( '%1$s is running in %2$s, please contact your host and ask them to disable it. BackUpWordPress may not work correctly whilst %3$s is on.', 'backupwordpress' ), '<code>PHP</code>', sprintf( '<a href="%1$s">%2$s</a>', __( 'http://php.net/manual/en/features.safe-mode.php', 'backupwordpress' ), __( 'Safe Mode', 'backupwordpress' ) ), '<code>' . __( 'Safe Mode', 'backupwordpress' ) . '</code>' );
129
  }
130
 
152
  }
153
  }
154
 
155
+ $test_backup = new HM\BackUpWordPress\Backup();
156
 
157
  if ( ! is_readable( $test_backup->get_root() ) ) {
158
  $messages[] = sprintf( __( 'Your site root path %s isn\'t readable.', 'backupwordpress' ), '<code>' . $test_backup->get_root() . '</code>' );
209
  *
210
  * @access public
211
  * @param string $type
212
+ * @param HM\BackUpWordPress\Scheduled_Backup $schedule (default: null)
213
  * @return string
214
  */
215
+ function hmbkp_human_get_type( $type, HM\BackUpWordPress\Scheduled_Backup $schedule = null ) {
216
 
217
+ if ( strpos( $type, 'complete' ) !== false ) {
218
  return __( 'Database and Files', 'backupwordpress' );
219
+ }
220
 
221
+ if ( strpos( $type, 'file' ) !== false ) {
222
  return __( 'Files', 'backupwordpress' );
223
+ }
224
 
225
+ if ( strpos( $type, 'database' ) !== false ) {
226
  return __( 'Database', 'backupwordpress' );
227
+ }
228
 
229
+ if ( ! is_null( $schedule ) ) {
230
  return hmbkp_human_get_type( $schedule->get_type() );
231
+ }
232
 
233
  return __( 'Legacy', 'backupwordpress' );
234
 
238
  * Display the row of actions for a schedule
239
  *
240
  * @access public
241
+ * @param HM\BackUpWordPress\Scheduled_Backup $schedule
242
  * @return void
243
  */
244
+ function hmbkp_schedule_status( HM\BackUpWordPress\Scheduled_Backup $schedule, $echo = true ) {
245
 
246
  ob_start(); ?>
247
 
267
  */
268
  function hmbkp_backup_errors() {
269
 
270
+ if ( ! file_exists( hmbkp_path() . '/.backup_errors' ) ) {
271
  return '';
272
+ }
273
 
274
  return file_get_contents( hmbkp_path() . '/.backup_errors' );
275
 
282
  */
283
  function hmbkp_backup_warnings() {
284
 
285
+ if ( ! file_exists( hmbkp_path() . '/.backup_warnings' ) ) {
286
  return '';
287
+ }
288
 
289
  return file_get_contents( hmbkp_path() . '/.backup_warnings' );
290
 
297
  if ( 0 === $number ) {
298
  $output = sprintf( __( 'No backups completed', 'backupwordpress' ) );
299
  } else {
300
+ $output = sprintf( _nx( 'One backup completed', '%1$s backups completed', $number, 'backups count', 'backupwordpress' ), number_format_i18n( $number ) );
 
301
  }
302
 
303
  echo apply_filters( 'hmbkp_backups_number', $output, $number );
345
  $url = admin_url( 'tools.php?page=' . HMBKP_PLUGIN_SLUG );
346
  }
347
 
348
+ HM\BackUpWordPress\schedules::get_instance()->refresh_schedules();
349
 
350
+ if ( ! empty( $_REQUEST['hmbkp_schedule_id'] ) && HM\BackUpWordPress\schedules::get_instance()->get_schedule( sanitize_text_field( $_REQUEST['hmbkp_schedule_id'] ) ) ) {
351
  $url = add_query_arg( 'hmbkp_schedule_id', sanitize_text_field( $_REQUEST['hmbkp_schedule_id'] ), $url );
352
  }
353
 
379
  * @return mixed
380
  */
381
  function hmbkp_get_settings_errors() {
 
382
  return get_transient( 'hmbkp_settings_errors' );
383
  }
384
 
hm-backup/CONTRIBUTING.md DELETED
@@ -1,13 +0,0 @@
1
- ## Contribution guidelines ##
2
-
3
- ## Workflow ##
4
-
5
- * Develop on a feature branch and send a pull request for review.
6
- * Assign the pull request to one of the following contacts:
7
- * Primary: Tom Willmot [@willmot](https://github.com/willmot)
8
- * Secondary:
9
-
10
- ## Coding Standards ##
11
-
12
- Please follow these recommendations
13
- [http://codex.wordpress.org/WordPress_Coding_Standards](http://codex.wordpress.org/WordPress_Coding_Standards)
 
 
 
 
 
 
 
 
 
 
 
 
 
hm-backup/README.md DELETED
@@ -1,8 +0,0 @@
1
- hm-backup
2
- =========
3
-
4
- The core backup engine that powers BackUpWordPress &amp; WP Remote
5
-
6
- ## Contribution guidelines ##
7
-
8
- see https://github.com/humanmade/hm-backup/blob/master/CONTRIBUTING.md
 
 
 
 
 
 
 
 
hm-backup/composer.json DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "name" : "humanmade/hm-backup",
3
- "description": "The core backup engine that powers BackUpWordPress & WP Remote",
4
- "keywords" : ["wordpress"],
5
- "homepage" : "https://github.com/humanmade/hm-backup",
6
- "license" : "GPL-2.0+",
7
- "authors" : [
8
- {
9
- "name" : "Human Made Limited",
10
- "email" : "hello@humanmade.co.uk",
11
- "homepage": "http://humanmade.co.uk"
12
- }
13
- ],
14
- "support" : {
15
- "issues": "https://github.com/humanmade/hm-backup/issues"
16
- },
17
- "autoload" : {
18
- "classmap": ["hm-backup.php"]
19
- }
20
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
hm-backup/hm-backup.php DELETED
@@ -1,1643 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Generic file and database backup class
5
- *
6
- * @version 2.2
7
- */
8
- class HM_Backup {
9
-
10
- /**
11
- * The path where the backup file should be saved
12
- *
13
- * @string
14
- */
15
- private $path = '';
16
-
17
- /**
18
- * The backup type, must be either complete, file or database
19
- *
20
- * @string
21
- */
22
- private $type = '';
23
-
24
- /**
25
- * The filename of the backup file
26
- *
27
- * @string
28
- */
29
- private $archive_filename = '';
30
-
31
- /**
32
- * The filename of the database dump
33
- *
34
- * @string
35
- */
36
- private $database_dump_filename = '';
37
-
38
- /**
39
- * The path to the zip command
40
- *
41
- * @string
42
- */
43
- private $zip_command_path;
44
-
45
- /**
46
- * The path to the mysqldump command
47
- *
48
- * @string
49
- */
50
- private $mysqldump_command_path;
51
-
52
- /**
53
- * An array of exclude rules
54
- *
55
- * @array
56
- */
57
- private $excludes = array();
58
-
59
- /**
60
- * The path that should be backed up
61
- *
62
- * @var string
63
- */
64
- private $root = '';
65
-
66
- /**
67
- * Holds the current db connection
68
- *
69
- * @var resource
70
- */
71
- private $db;
72
-
73
- /**
74
- * An array of all the files in root
75
- * excluding excludes and unreadable files
76
- *
77
- * @var array
78
- */
79
- private $files = array();
80
-
81
- /**
82
- * An array of all the files in root
83
- * that match the exclude rules
84
- *
85
- * @var array
86
- */
87
- private $excluded_files = array();
88
-
89
- /**
90
- * An array of all the files in root
91
- * that are unreadable
92
- *
93
- * @var array
94
- */
95
- private $unreadable_files = array();
96
-
97
- /**
98
- * An array of all the files in root
99
- * that will be included in the backup
100
- *
101
- * @var array
102
- */
103
- protected $included_files = array();
104
-
105
- /**
106
- * Contains an array of errors
107
- *
108
- * @var mixed
109
- */
110
- private $errors = array();
111
-
112
- /**
113
- * Contains an array of warnings
114
- *
115
- * @var mixed
116
- */
117
- private $warnings = array();
118
-
119
- /**
120
- * The archive method used
121
- *
122
- * @var string
123
- */
124
- private $archive_method = '';
125
-
126
- /**
127
- * The mysqldump method used
128
- *
129
- * @var string
130
- */
131
- private $mysqldump_method = '';
132
-
133
- /**
134
- * @var bool
135
- */
136
- protected $mysqldump_verified = false;
137
-
138
- /**
139
- * @var bool
140
- */
141
- protected $archive_verified = false;
142
-
143
- /**
144
- * Check whether safe mode is active or not
145
- *
146
- * @param string $ini_get_callback
147
- * @return bool
148
- */
149
- public static function is_safe_mode_active( $ini_get_callback = 'ini_get' ) {
150
-
151
- if ( ( $safe_mode = @call_user_func( $ini_get_callback, 'safe_mode' ) ) && strtolower( $safe_mode ) != 'off' )
152
- return true;
153
-
154
- return false;
155
-
156
- }
157
-
158
- /**
159
- * Check whether shell_exec has been disabled.
160
- *
161
- * @return bool
162
- */
163
- public static function is_shell_exec_available() {
164
-
165
- // Are we in Safe Mode
166
- if ( self::is_safe_mode_active() )
167
- return false;
168
-
169
- // Is shell_exec or escapeshellcmd or escapeshellarg disabled?
170
- if ( array_intersect( array( 'shell_exec', 'escapeshellarg', 'escapeshellcmd' ), array_map( 'trim', explode( ',', @ini_get( 'disable_functions' ) ) ) ) )
171
- return false;
172
-
173
- // Functions can also be disabled via suhosin
174
- if ( array_intersect( array( 'shell_exec', 'escapeshellarg', 'escapeshellcmd' ), array_map( 'trim', explode( ',', @ini_get( 'suhosin.executor.func.blacklist' ) ) ) ) )
175
- return false;
176
-
177
- // Can we issue a simple echo command?
178
- if ( ! @shell_exec( 'echo backupwordpress' ) )
179
- return false;
180
-
181
- return true;
182
-
183
- }
184
-
185
-
186
- /**
187
- * Attempt to work out the root directory of the site, that
188
- * is, the path equivelant of home_url().
189
- *
190
- * @return string $home_path
191
- */
192
- public static function get_home_path() {
193
-
194
- $home_url = home_url();
195
- $site_url = site_url();
196
-
197
- $home_path = ABSPATH;
198
-
199
- // If site_url contains home_url and they differ then assume WordPress is installed in a sub directory
200
- if ( $home_url !== $site_url && strpos( $site_url, $home_url ) === 0 ) {
201
- $home_path = trailingslashit( substr( self::conform_dir( ABSPATH ), 0, strrpos( self::conform_dir( ABSPATH ), str_replace( $home_url, '', $site_url ) ) ) );
202
- }
203
-
204
- return self::conform_dir( $home_path );
205
-
206
- }
207
-
208
-
209
- /**
210
- * Sanitize a directory path
211
- *
212
- * @param string $dir
213
- * @param bool $recursive
214
- * @return string
215
- */
216
- public static function conform_dir( $dir, $recursive = false ) {
217
-
218
- // Assume empty dir is root
219
- if ( ! $dir )
220
- $dir = '/';
221
-
222
- // Replace single forward slash (looks like double slash because we have to escape it)
223
- $dir = str_replace( '\\', '/', $dir );
224
- $dir = str_replace( '//', '/', $dir );
225
-
226
- // Remove the trailing slash
227
- if ( $dir !== '/' )
228
- $dir = untrailingslashit( $dir );
229
-
230
- // Carry on until completely normalized
231
- if ( ! $recursive && self::conform_dir( $dir, true ) != $dir )
232
- return self::conform_dir( $dir );
233
-
234
- return (string) $dir;
235
-
236
- }
237
-
238
- /**
239
- * Sets up the default properties
240
- */
241
- public function __construct() {
242
-
243
- // Raise the memory limit and max_execution time
244
- @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
245
- @set_time_limit( 0 );
246
-
247
- // Set a custom error handler so we can track errors
248
- set_error_handler( array( $this, 'error_handler' ) );
249
-
250
- }
251
-
252
- /**
253
- * Get the full filepath to the archive file
254
- *
255
- * @return string
256
- */
257
- public function get_archive_filepath() {
258
-
259
- return trailingslashit( $this->get_path() ) . $this->get_archive_filename();
260
-
261
- }
262
-
263
- /**
264
- * Get the filename of the archive file
265
- *
266
- * @return string
267
- */
268
- public function get_archive_filename() {
269
-
270
- if ( empty( $this->archive_filename ) )
271
- $this->set_archive_filename( implode( '-', array( sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ), 'backup', date( 'Y-m-d-H-i-s', current_time( 'timestamp' ) ) ) ) . '.zip' );
272
-
273
- return $this->archive_filename;
274
-
275
- }
276
-
277
- /**
278
- * Set the filename of the archive file
279
- *
280
- * @param string $filename
281
- * @return WP_Error
282
- */
283
- public function set_archive_filename( $filename ) {
284
-
285
- if ( empty( $filename ) || ! is_string( $filename ) )
286
- return new WP_Error( 'invalid_file_name', __( 'archive filename must be a non empty string', 'backupwordpress' ) );
287
-
288
- if ( pathinfo( $filename, PATHINFO_EXTENSION ) !== 'zip' )
289
- return new WP_Error( 'invalid_file_extension', sprintf( __( 'invalid file extension for archive filename <code>%s</code>', 'backupwordpress' ), $filename ) );
290
-
291
- $this->archive_filename = strtolower( sanitize_file_name( remove_accents( $filename ) ) );
292
-
293
- }
294
-
295
- /**
296
- * Get the full filepath to the database dump file.
297
- *
298
- * @return string
299
- */
300
- public function get_database_dump_filepath() {
301
-
302
- return trailingslashit( $this->get_path() ) . $this->get_database_dump_filename();
303
-
304
- }
305
-
306
- /**
307
- * Get the filename of the database dump file
308
- *
309
- * @return string
310
- */
311
- public function get_database_dump_filename() {
312
-
313
- if ( empty( $this->database_dump_filename ) )
314
- $this->set_database_dump_filename( 'database_' . DB_NAME . '.sql' );
315
-
316
- return $this->database_dump_filename;
317
-
318
- }
319
-
320
- /**
321
- * Set the filename of the database dump file
322
- *
323
- * @param string $filename
324
- * @return WP_Error
325
- */
326
- public function set_database_dump_filename( $filename ) {
327
-
328
- if ( empty( $filename ) || ! is_string( $filename ) )
329
- return new WP_Error( 'invalid_file_name', __( 'database dump filename must be a non empty string', 'backupwordpress' ) );
330
-
331
- if ( pathinfo( $filename, PATHINFO_EXTENSION ) !== 'sql' )
332
- return new WP_Error( 'invalid_file_extension', sprintf( __( 'invalid file extension for database dump filename <code>%s</code>', 'backupwordpress' ), $filename ) );
333
-
334
- $this->database_dump_filename = strtolower( sanitize_file_name( remove_accents( $filename ) ) );
335
-
336
- }
337
-
338
- /**
339
- * Get the root directory to backup from
340
- *
341
- * Defaults to the root of the path equivalent of your home_url
342
- *
343
- * @return string
344
- */
345
- public function get_root() {
346
-
347
- if ( empty( $this->root ) )
348
- $this->set_root( self::conform_dir( self::get_home_path() ) );
349
-
350
- return $this->root;
351
-
352
- }
353
-
354
- /**
355
- * Set the root directory to backup from
356
- *
357
- * @param string $path
358
- * @return WP_Error
359
- */
360
- public function set_root( $path ) {
361
-
362
- if ( empty( $path ) || ! is_string( $path ) || ! is_dir( $path ) )
363
- return new WP_Error( 'invalid_directory_path', sprintf( __( 'Invalid root path <code>%s</code> must be a valid directory path', 'backupwordpress' ), $path ) );
364
-
365
- $this->root = self::conform_dir( $path );
366
-
367
- }
368
-
369
- /**
370
- * Get the directory backups are saved to
371
- *
372
- * @return string
373
- */
374
- public function get_path() {
375
-
376
- if ( empty( $this->path ) )
377
- $this->set_path( self::conform_dir( hmbkp_path() ) );
378
-
379
- return $this->path;
380
-
381
- }
382
-
383
- /**
384
- * Set the directory backups are saved to
385
- *
386
- * @param string $path
387
- * @return null
388
- */
389
- public function set_path( $path ) {
390
-
391
- if ( empty( $path ) || ! is_string( $path ) )
392
- return new WP_Error( 'invalid_backup_path', sprintf( __( 'Invalid backup path <code>%s</code> must be a non empty (string)', 'backupwordpress' ), $path ) );
393
-
394
- $this->path = self::conform_dir( $path );
395
-
396
- }
397
-
398
- /**
399
- * Get the archive method that was used for the backup
400
- *
401
- * Will be either zip, ZipArchive or PclZip
402
- *
403
- */
404
- public function get_archive_method() {
405
- return $this->archive_method;
406
- }
407
-
408
- /**
409
- * Get the database dump method that was used for the backup
410
- *
411
- * Will be either mysqldump or mysqldump_fallback
412
- *
413
- */
414
- public function get_mysqldump_method() {
415
- return $this->mysqldump_method;
416
- }
417
-
418
- /**
419
- * Get the backup type
420
- *
421
- * Defaults to complete
422
- *
423
- */
424
- public function get_type() {
425
-
426
- if ( empty( $this->type ) )
427
- $this->set_type( 'complete' );
428
-
429
- return $this->type;
430
-
431
- }
432
-
433
- /**
434
- * Set the backup type
435
- *
436
- * $type must be one of complete, database or file
437
- *
438
- * @param string $type
439
- * @return WP_Error
440
- */
441
- public function set_type( $type ) {
442
-
443
- if ( ! is_string( $type ) || ! in_array( $type, array( 'file', 'database', 'complete' ) ) )
444
- return new WP_Error( 'invalid_backup_type', sprintf( __( 'Invalid backup type <code>%s</code> must be one of (string) file, database or complete', 'backupwordpress' ), $type ) );
445
-
446
- $this->type = $type;
447
-
448
- }
449
-
450
- /**
451
- * Get the path to the mysqldump bin
452
- *
453
- * If not explicitly set will attempt to work
454
- * it out by checking common locations
455
- *
456
- * @return string
457
- */
458
- public function get_mysqldump_command_path() {
459
-
460
- // Check shell_exec is available
461
- if ( ! self::is_shell_exec_available() )
462
- return '';
463
-
464
- // Return now if it's already been set
465
- if ( isset( $this->mysqldump_command_path ) )
466
- return $this->mysqldump_command_path;
467
-
468
- $this->mysqldump_command_path = '';
469
-
470
- // Does mysqldump work
471
- if ( is_null( shell_exec( 'hash mysqldump 2>&1' ) ) ) {
472
-
473
- // If so store it for later
474
- $this->set_mysqldump_command_path( 'mysqldump' );
475
-
476
- // And return now
477
- return $this->mysqldump_command_path;
478
-
479
- }
480
-
481
- // List of possible mysqldump locations
482
- $mysqldump_locations = array(
483
- '/usr/local/bin/mysqldump',
484
- '/usr/local/mysql/bin/mysqldump',
485
- '/usr/mysql/bin/mysqldump',
486
- '/usr/bin/mysqldump',
487
- '/opt/local/lib/mysql6/bin/mysqldump',
488
- '/opt/local/lib/mysql5/bin/mysqldump',
489
- '/opt/local/lib/mysql4/bin/mysqldump',
490
- '/xampp/mysql/bin/mysqldump',
491
- '/Program Files/xampp/mysql/bin/mysqldump',
492
- '/Program Files/MySQL/MySQL Server 6.0/bin/mysqldump',
493
- '/Program Files/MySQL/MySQL Server 5.5/bin/mysqldump',
494
- '/Program Files/MySQL/MySQL Server 5.4/bin/mysqldump',
495
- '/Program Files/MySQL/MySQL Server 5.1/bin/mysqldump',
496
- '/Program Files/MySQL/MySQL Server 5.0/bin/mysqldump',
497
- '/Program Files/MySQL/MySQL Server 4.1/bin/mysqldump',
498
- '/opt/local/bin/mysqldump'
499
- );
500
-
501
- // Find the first one which works
502
- foreach ( $mysqldump_locations as $location ) {
503
- if ( @is_executable( self::conform_dir( $location ) ) ) {
504
- $this->set_mysqldump_command_path( $location );
505
- break; // Found one
506
- }
507
- }
508
-
509
- return $this->mysqldump_command_path;
510
-
511
- }
512
-
513
- /**
514
- * Set the path to the mysqldump bin
515
- *
516
- * Setting the path to false will cause the database
517
- * dump to use the php fallback
518
- *
519
- * @param mixed $path
520
- */
521
- public function set_mysqldump_command_path( $path ) {
522
-
523
- $this->mysqldump_command_path = $path;
524
-
525
- }
526
-
527
- /**
528
- * Get the path to the zip bin
529
- *
530
- * If not explicitly set will attempt to work
531
- * it out by checking common locations
532
- *
533
- * @return string
534
- */
535
- public function get_zip_command_path() {
536
-
537
- // Check shell_exec is available
538
- if ( ! self::is_shell_exec_available() )
539
- return '';
540
-
541
- // Return now if it's already been set
542
- if ( isset( $this->zip_command_path ) )
543
- return $this->zip_command_path;
544
-
545
- $this->zip_command_path = '';
546
-
547
- // Does zip work
548
- if ( is_null( shell_exec( 'hash zip 2>&1' ) ) ) {
549
-
550
- // If so store it for later
551
- $this->set_zip_command_path( 'zip' );
552
-
553
- // And return now
554
- return $this->zip_command_path;
555
-
556
- }
557
-
558
- // List of possible zip locations
559
- $zip_locations = array(
560
- '/usr/bin/zip',
561
- '/opt/local/bin/zip'
562
- );
563
-
564
- // Find the first one which works
565
- foreach ( $zip_locations as $location ) {
566
- if ( @is_executable( self::conform_dir( $location ) ) ) {
567
- $this->set_zip_command_path( $location );
568
- break; // Found one
569
- }
570
- }
571
-
572
- return $this->zip_command_path;
573
-
574
- }
575
-
576
- /**
577
- * Set the path to the zip bin
578
- *
579
- * Setting the path to false will cause the database
580
- * dump to use the php fallback
581
- *
582
- * @param mixed $path
583
- */
584
- public function set_zip_command_path( $path ) {
585
-
586
- $this->zip_command_path = $path;
587
-
588
- }
589
-
590
- protected function do_action( $action ) {
591
-
592
- do_action( $action, $this );
593
-
594
- }
595
-
596
- /**
597
- * Kick off a backup
598
- *
599
- * @return bool
600
- */
601
- public function backup() {
602
-
603
- $this->do_action( 'hmbkp_backup_started' );
604
-
605
- // Backup database
606
- if ( $this->get_type() !== 'file' )
607
- $this->dump_database();
608
-
609
- // Zip everything up
610
- $this->archive();
611
-
612
- $this->do_action( 'hmbkp_backup_complete' );
613
-
614
- }
615
-
616
- /**
617
- * Create the mysql backup
618
- *
619
- * Uses mysqldump if available, falls back to PHP
620
- * if not.
621
- *
622
- */
623
- public function dump_database() {
624
-
625
- if ( $this->get_mysqldump_command_path() )
626
- $this->mysqldump();
627
-
628
- if ( empty( $this->mysqldump_verified ) )
629
- $this->mysqldump_fallback();
630
-
631
- $this->do_action( 'hmbkp_mysqldump_finished' );
632
-
633
- }
634
-
635
- public function mysqldump() {
636
-
637
- $this->mysqldump_method = 'mysqldump';
638
-
639
- $this->do_action( 'hmbkp_mysqldump_started' );
640
-
641
- $host = explode( ':', DB_HOST );
642
-
643
- $host = reset( $host );
644
- $port = strpos( DB_HOST, ':' ) ? end( explode( ':', DB_HOST ) ) : '';
645
-
646
- // Path to the mysqldump executable
647
- $cmd = escapeshellarg( $this->get_mysqldump_command_path() );
648
-
649
- // We don't want to create a new DB
650
- $cmd .= ' --no-create-db';
651
-
652
- // Allow lock-tables to be overridden
653
- if ( ! defined( 'HMBKP_MYSQLDUMP_SINGLE_TRANSACTION' ) || HMBKP_MYSQLDUMP_SINGLE_TRANSACTION !== false )
654
- $cmd .= ' --single-transaction';
655
-
656
- // Make sure binary data is exported properly
657
- $cmd .= ' --hex-blob';
658
-
659
- // Username
660
- $cmd .= ' -u ' . escapeshellarg( DB_USER );
661
-
662
- // Don't pass the password if it's blank
663
- if ( DB_PASSWORD )
664
- $cmd .= ' -p' . escapeshellarg( DB_PASSWORD );
665
-
666
- // Set the host
667
- $cmd .= ' -h ' . escapeshellarg( $host );
668
-
669
- // Set the port if it was set
670
- if ( ! empty( $port ) && is_numeric( $port ) )
671
- $cmd .= ' -P ' . $port;
672
-
673
- // The file we're saving too
674
- $cmd .= ' -r ' . escapeshellarg( $this->get_database_dump_filepath() );
675
-
676
- // The database we're dumping
677
- $cmd .= ' ' . escapeshellarg( DB_NAME );
678
-
679
- // Pipe STDERR to STDOUT
680
- $cmd .= ' 2>&1';
681
-
682
- // Store any returned data in an error
683
- $stderr = shell_exec( $cmd );
684
-
685
- // Skip the new password warning that is output in mysql > 5.6 (@see http://bugs.mysql.com/bug.php?id=66546)
686
- if ( trim( $stderr ) === 'Warning: Using a password on the command line interface can be insecure.' ) {
687
- $stderr = '';
688
- }
689
-
690
- if ( $stderr ) {
691
- $this->error( $this->get_mysqldump_method(), $stderr );
692
- }
693
-
694
- $this->verify_mysqldump();
695
-
696
- }
697
-
698
- /**
699
- * PHP mysqldump fallback functions, exports the database to a .sql file
700
- *
701
- */
702
- public function mysqldump_fallback() {
703
-
704
- $this->errors_to_warnings( $this->get_mysqldump_method() );
705
-
706
- $this->mysqldump_method = 'mysqldump_fallback';
707
-
708
- $this->do_action( 'hmbkp_mysqldump_started' );
709
-
710
- $this->db = @mysql_pconnect( DB_HOST, DB_USER, DB_PASSWORD );
711
-
712
- if ( ! $this->db )
713
- $this->db = mysql_connect( DB_HOST, DB_USER, DB_PASSWORD );
714
-
715
- if ( ! $this->db )
716
- return;
717
-
718
- mysql_select_db( DB_NAME, $this->db );
719
-
720
- if ( function_exists( 'mysql_set_charset' ) )
721
- mysql_set_charset( DB_CHARSET, $this->db );
722
-
723
- // Begin new backup of MySql
724
- $tables = mysql_query( 'SHOW TABLES' );
725
-
726
- $sql_file = "# WordPress : " . get_bloginfo( 'url' ) . " MySQL database backup\n";
727
- $sql_file .= "#\n";
728
- $sql_file .= "# Generated: " . date( 'l j. F Y H:i T' ) . "\n";
729
- $sql_file .= "# Hostname: " . DB_HOST . "\n";
730
- $sql_file .= "# Database: " . $this->sql_backquote( DB_NAME ) . "\n";
731
- $sql_file .= "# --------------------------------------------------------\n";
732
-
733
- for ( $i = 0; $i < mysql_num_rows( $tables ); $i ++ ) {
734
-
735
- $curr_table = mysql_tablename( $tables, $i );
736
-
737
- // Create the SQL statements
738
- $sql_file .= "# --------------------------------------------------------\n";
739
- $sql_file .= "# Table: " . $this->sql_backquote( $curr_table ) . "\n";
740
- $sql_file .= "# --------------------------------------------------------\n";
741
-
742
- $this->make_sql( $sql_file, $curr_table );
743
-
744
- }
745
-
746
- }
747
-
748
- /**
749
- * Zip up all the files.
750
- *
751
- * Attempts to use the shell zip command, if
752
- * thats not available then it falls back to
753
- * PHP ZipArchive and finally PclZip.
754
- *
755
- */
756
- public function archive() {
757
-
758
- // Do we have the path to the zip command
759
- if ( $this->get_zip_command_path() )
760
- $this->zip();
761
-
762
- // If not or if the shell zip failed then use ZipArchive
763
- if ( empty( $this->archive_verified ) && class_exists( 'ZipArchive' ) && empty( $this->skip_zip_archive ) )
764
- $this->zip_archive();
765
-
766
- // If ZipArchive is unavailable or one of the above failed
767
- if ( empty( $this->archive_verified ) )
768
- $this->pcl_zip();
769
-
770
- // Delete the database dump file
771
- if ( file_exists( $this->get_database_dump_filepath() ) )
772
- unlink( $this->get_database_dump_filepath() );
773
-
774
- $this->do_action( 'hmbkp_archive_finished' );
775
-
776
- }
777
-
778
- /**
779
- * Zip using the native zip command
780
- */
781
- public function zip() {
782
-
783
- $this->archive_method = 'zip';
784
-
785
- $this->do_action( 'hmbkp_archive_started' );
786
-
787
- // Zip up $this->root with excludes
788
- if ( $this->get_type() !== 'database' && $this->exclude_string( 'zip' ) )
789
- $stderr = shell_exec( 'cd ' . escapeshellarg( $this->get_root() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -rq ' . escapeshellarg( $this->get_archive_filepath() ) . ' ./' . ' -x ' . $this->exclude_string( 'zip' ) . ' 2>&1' );
790
-
791
- // Zip up $this->root without excludes
792
- elseif ( $this->get_type() !== 'database' )
793
- $stderr = shell_exec( 'cd ' . escapeshellarg( $this->get_root() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -rq ' . escapeshellarg( $this->get_archive_filepath() ) . ' ./' . ' 2>&1' );
794
-
795
- // Add the database dump to the archive
796
- if ( $this->get_type() !== 'file' && file_exists( $this->get_database_dump_filepath() ) )
797
- $stderr = shell_exec( 'cd ' . escapeshellarg( $this->get_path() ) . ' && ' . escapeshellcmd( $this->get_zip_command_path() ) . ' -uq ' . escapeshellarg( $this->get_archive_filepath() ) . ' ' . escapeshellarg( $this->get_database_dump_filename() ) . ' 2>&1' );
798
-
799
- if ( ! empty( $stderr ) )
800
- $this->warning( $this->get_archive_method(), $stderr );
801
-
802
- $this->verify_archive();
803
-
804
- }
805
-
806
- /**
807
- * Fallback for creating zip archives if zip command is
808
- * unavailable.
809
- */
810
- public function zip_archive() {
811
-
812
- $this->errors_to_warnings( $this->get_archive_method() );
813
- $this->archive_method = 'ziparchive';
814
-
815
- $this->do_action( 'hmbkp_archive_started' );
816
-
817
- $zip = new ZipArchive();
818
-
819
- if ( ! class_exists( 'ZipArchive' ) || ! $zip->open( $this->get_archive_filepath(), ZIPARCHIVE::CREATE ) )
820
- return;
821
-
822
- $excludes = $this->exclude_string( 'regex' );
823
-
824
- if ( $this->get_type() !== 'database' ) {
825
-
826
- $files_added = 0;
827
-
828
- foreach ( $this->get_files() as $file ) {
829
-
830
- // Skip dot files, they should only exist on versions of PHP between 5.2.11 -> 5.3
831
- if ( method_exists( $file, 'isDot' ) && $file->isDot() )
832
- continue;
833
-
834
- // Skip unreadable files
835
- if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() )
836
- continue;
837
-
838
- // Excludes
839
- if ( $excludes && preg_match( '(' . $excludes . ')', str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) ) )
840
- continue;
841
-
842
- if ( $file->isDir() )
843
- $zip->addEmptyDir( trailingslashit( str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) ) );
844
-
845
- elseif ( $file->isFile() )
846
- $zip->addFile( $file->getPathname(), str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) );
847
-
848
- if ( ++$files_added % 500 === 0 )
849
- if ( ! $zip->close() || ! $zip->open( $this->get_archive_filepath(), ZIPARCHIVE::CREATE ) )
850
- return;
851
-
852
- }
853
-
854
- }
855
-
856
- // Add the database
857
- if ( $this->get_type() !== 'file' && file_exists( $this->get_database_dump_filepath() ) )
858
- $zip->addFile( $this->get_database_dump_filepath(), $this->get_database_dump_filename() );
859
-
860
- if ( $zip->status )
861
- $this->warning( $this->get_archive_method(), $zip->status );
862
-
863
- if ( $zip->statusSys )
864
- $this->warning( $this->get_archive_method(), $zip->statusSys );
865
-
866
- $zip->close();
867
-
868
- $this->verify_archive();
869
-
870
- }
871
-
872
- /**
873
- * Fallback for creating zip archives if zip command and ZipArchive are
874
- * unavailable.
875
- *
876
- * Uses the PclZip library that ships with WordPress
877
- */
878
- public function pcl_zip() {
879
-
880
- $this->errors_to_warnings( $this->get_archive_method() );
881
- $this->archive_method = 'pclzip';
882
-
883
- $this->do_action( 'hmbkp_archive_started' );
884
-
885
- global $_hmbkp_exclude_string;
886
-
887
- $_hmbkp_exclude_string = $this->exclude_string( 'regex' );
888
-
889
- $this->load_pclzip();
890
-
891
- $archive = new PclZip( $this->get_archive_filepath() );
892
-
893
- // Zip up everything
894
- if ( $this->get_type() !== 'database' )
895
- if ( ! $archive->add( $this->get_root(), PCLZIP_OPT_REMOVE_PATH, $this->get_root(), PCLZIP_CB_PRE_ADD, 'hmbkp_pclzip_callback' ) )
896
- $this->warning( $this->get_archive_method(), $archive->errorInfo( true ) );
897
-
898
- // Add the database
899
- if ( $this->get_type() !== 'file' && file_exists( $this->get_database_dump_filepath() ) )
900
- if ( ! $archive->add( $this->get_database_dump_filepath(), PCLZIP_OPT_REMOVE_PATH, $this->get_path() ) )
901
- $this->warning( $this->get_archive_method(), $archive->errorInfo( true ) );
902
-
903
- unset( $GLOBALS['_hmbkp_exclude_string'] );
904
-
905
- $this->verify_archive();
906
-
907
- }
908
-
909
- public function verify_mysqldump() {
910
-
911
- $this->do_action( 'hmbkp_mysqldump_verify_started' );
912
-
913
- // If we've already passed then no need to check again
914
- if ( ! empty( $this->mysqldump_verified ) )
915
- return true;
916
-
917
- // If there are mysqldump errors delete the database dump file as mysqldump will still have written one
918
- if ( $this->get_errors( $this->get_mysqldump_method() ) && file_exists( $this->get_database_dump_filepath() ) )
919
- unlink( $this->get_database_dump_filepath() );
920
-
921
- // If we have an empty file delete it
922
- if ( @filesize( $this->get_database_dump_filepath() ) === 0 )
923
- unlink( $this->get_database_dump_filepath() );
924
-
925
- // If the file still exists then it must be good
926
- if ( file_exists( $this->get_database_dump_filepath() ) )
927
- return $this->mysqldump_verified = true;
928
-
929
- return false;
930
-
931
-
932
- }
933
-
934
- /**
935
- * Verify that the archive is valid and contains all the files it should contain.
936
- *
937
- * @return bool
938
- */
939
- public function verify_archive() {
940
-
941
- $this->do_action( 'hmbkp_archive_verify_started' );
942
-
943
- // If we've already passed then no need to check again
944
- if ( ! empty( $this->archive_verified ) )
945
- return true;
946
-
947
- // If there are errors delete the backup file.
948
- if ( $this->get_errors( $this->get_archive_method() ) && file_exists( $this->get_archive_filepath() ) )
949
- unlink( $this->get_archive_filepath() );
950
-
951
- // If the archive file still exists assume it's good
952
- if ( file_exists( $this->get_archive_filepath() ) )
953
- return $this->archive_verified = true;
954
-
955
- return false;
956
-
957
- }
958
-
959
- /**
960
- * Return an array of all files in the filesystem
961
- *
962
- * @return array
963
- */
964
- public function get_files() {
965
-
966
- if ( ! empty( $this->files ) )
967
- return $this->files;
968
-
969
- $this->files = array();
970
-
971
- // We only want to use the RecursiveDirectoryIterator if the FOLLOW_SYMLINKS flag is available
972
- if ( defined( 'RecursiveDirectoryIterator::FOLLOW_SYMLINKS' ) ) {
973
-
974
- $this->files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $this->get_root(), RecursiveDirectoryIterator::FOLLOW_SYMLINKS ), RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
975
-
976
- // Skip dot files if the SKIP_DOTS flag is available
977
- if ( defined( 'RecursiveDirectoryIterator::SKIP_DOTS' ) ) {
978
- $this->files->setFlags( RecursiveDirectoryIterator::SKIP_DOTS + RecursiveDirectoryIterator::FOLLOW_SYMLINKS );
979
- }
980
-
981
- // If RecursiveDirectoryIterator::FOLLOW_SYMLINKS isn't available then fallback to a less memory efficient method
982
- } else {
983
-
984
- $this->files = $this->get_files_fallback( $this->get_root() );
985
-
986
- }
987
-
988
- return $this->files;
989
-
990
- }
991
-
992
- /**
993
- * Fallback function for generating a filesystem
994
- * array
995
- *
996
- * Used if RecursiveDirectoryIterator::FOLLOW_SYMLINKS isn't available
997
- *
998
- * @param string $dir
999
- * @param array $files. (default: array())
1000
- * @return array
1001
- */
1002
- private function get_files_fallback( $dir, $files = array() ) {
1003
-
1004
- $handle = opendir( $dir );
1005
-
1006
- $excludes = $this->exclude_string( 'regex' );
1007
-
1008
- while ( $file = readdir( $handle ) ) :
1009
-
1010
- // Ignore current dir and containing dir
1011
- if ( $file === '.' || $file === '..' )
1012
- continue;
1013
-
1014
- $filepath = self::conform_dir( trailingslashit( $dir ) . $file );
1015
- $file = str_ireplace( trailingslashit( $this->get_root() ), '', $filepath );
1016
-
1017
- $files[] = new SplFileInfo( $filepath );
1018
-
1019
- if ( is_dir( $filepath ) )
1020
- $files = $this->get_files_fallback( $filepath, $files );
1021
-
1022
- endwhile;
1023
-
1024
- return $files;
1025
-
1026
- }
1027
-
1028
- /**
1029
- * Returns an array of files that will be included in the backup.
1030
- *
1031
- * @return array
1032
- */
1033
- public function get_included_files() {
1034
-
1035
- if ( ! empty( $this->included_files ) )
1036
- return $this->included_files;
1037
-
1038
- $this->included_files = array();
1039
-
1040
- $excludes = $this->exclude_string( 'regex' );
1041
-
1042
- foreach ( $this->get_files() as $file ) {
1043
-
1044
- // Skip dot files, they should only exist on versions of PHP between 5.2.11 -> 5.3
1045
- if ( method_exists( $file, 'isDot' ) && $file->isDot() )
1046
- continue;
1047
-
1048
- // Skip unreadable files
1049
- if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() )
1050
- continue;
1051
-
1052
- // Excludes
1053
- if ( $excludes && preg_match( '(' . $excludes . ')', str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) ) )
1054
- continue;
1055
-
1056
- $this->included_files[] = $file;
1057
-
1058
- }
1059
-
1060
- return $this->included_files;
1061
-
1062
- }
1063
-
1064
- /**
1065
- * Returns an array of files that match the exclude rules.
1066
- *
1067
- * @return array
1068
- */
1069
- public function get_excluded_files() {
1070
-
1071
- if ( ! empty( $this->excluded_files ) )
1072
- return $this->excluded_files;
1073
-
1074
- $this->excluded_files = array();
1075
-
1076
- $excludes = $this->exclude_string( 'regex' );
1077
-
1078
- foreach ( $this->get_files() as $file ) {
1079
-
1080
- // Skip dot files, they should only exist on versions of PHP between 5.2.11 -> 5.3
1081
- if ( method_exists( $file, 'isDot' ) && $file->isDot() )
1082
- continue;
1083
-
1084
- // Skip unreadable files
1085
- if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() )
1086
- continue;
1087
-
1088
- // Excludes
1089
- if ( $excludes && preg_match( '(' . $excludes . ')', str_ireplace( trailingslashit( $this->get_root() ), '', self::conform_dir( $file->getPathname() ) ) ) )
1090
- $this->excluded_files[] = $file;
1091
-
1092
- }
1093
-
1094
- return $this->excluded_files;
1095
-
1096
- }
1097
-
1098
- /**
1099
- * Returns an array of unreadable files.
1100
- *
1101
- * @return array
1102
- */
1103
- public function get_unreadable_files() {
1104
-
1105
- if ( ! empty( $this->unreadable_files ) )
1106
- return $this->unreadable_files;
1107
-
1108
- $this->unreadable_files = array();
1109
-
1110
- foreach ( $this->get_files() as $file ) {
1111
-
1112
- // Skip dot files, they should only exist on versions of PHP between 5.2.11 -> 5.3
1113
- if ( method_exists( $file, 'isDot' ) && $file->isDot() )
1114
- continue;
1115
-
1116
- if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() )
1117
- $this->unreadable_files[] = $file;
1118
-
1119
- }
1120
-
1121
- return $this->unreadable_files;
1122
-
1123
- }
1124
-
1125
- private function load_pclzip() {
1126
-
1127
- // Load PclZip
1128
- if ( ! defined( 'PCLZIP_TEMPORARY_DIR' ) )
1129
- define( 'PCLZIP_TEMPORARY_DIR', trailingslashit( $this->get_path() ) );
1130
-
1131
- require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
1132
-
1133
- }
1134
-
1135
- /**
1136
- * Get an array of exclude rules
1137
- *
1138
- * The backup path is automatically excluded
1139
- *
1140
- * @return array
1141
- */
1142
- public function get_excludes() {
1143
-
1144
- $excludes = array();
1145
-
1146
- if ( isset( $this->excludes ) ) {
1147
- $excludes = $this->excludes;
1148
- }
1149
-
1150
- // If path() is inside root(), exclude it
1151
- if ( strpos( $this->get_path(), $this->get_root() ) !== false ) {
1152
- array_unshift( $excludes, trailingslashit( $this->get_path() ) );
1153
- }
1154
-
1155
- return array_unique( $excludes );
1156
-
1157
- }
1158
-
1159
- /**
1160
- * Set the excludes, expects and array
1161
- *
1162
- * @param Array $excludes
1163
- * @param Bool $append
1164
- */
1165
- public function set_excludes( $excludes, $append = false ) {
1166
-
1167
- if ( is_string( $excludes ) ) {
1168
- $excludes = explode( ',', $excludes );
1169
- }
1170
-
1171
- if ( $append ) {
1172
- $excludes = array_merge( $this->excludes, $excludes );
1173
- }
1174
-
1175
- $this->excludes = array_filter( array_unique( array_map( 'trim', $excludes ) ) );
1176
-
1177
- }
1178
-
1179
- /**
1180
- * Generate the exclude param string for the zip backup
1181
- *
1182
- * Takes the exclude rules and formats them for use with either
1183
- * the shell zip command or pclzip
1184
- *
1185
- * @param string $context. (default: 'zip')
1186
- * @return string
1187
- */
1188
- public function exclude_string( $context = 'zip' ) {
1189
-
1190
- // Return a comma separated list by default
1191
- $separator = ', ';
1192
- $wildcard = '';
1193
-
1194
- // The zip command
1195
- if ( $context === 'zip' ) {
1196
- $wildcard = '*';
1197
- $separator = ' -x ';
1198
-
1199
- // The PclZip fallback library
1200
- }
1201
- elseif ( $context === 'regex' ) {
1202
- $wildcard = '([\s\S]*?)';
1203
- $separator = '|';
1204
-
1205
- }
1206
-
1207
- $excludes = $this->get_excludes();
1208
-
1209
- foreach ( $excludes as $key => &$rule ) {
1210
-
1211
- $file = $absolute = $fragment = false;
1212
-
1213
- // Files don't end with /
1214
- if ( ! in_array( substr( $rule, - 1 ), array( '\\', '/' ) ) ) {
1215
- $file = true;
1216
- }
1217
-
1218
- // If rule starts with a / then treat as absolute path
1219
- elseif ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) ) {
1220
- $absolute = true;
1221
- }
1222
-
1223
- // Otherwise treat as dir fragment
1224
- else {
1225
- $fragment = true;
1226
- }
1227
-
1228
- // Strip $this->root and conform
1229
- $rule = str_ireplace( $this->get_root(), '', untrailingslashit( self::conform_dir( $rule ) ) );
1230
-
1231
-
1232
- // Strip the preceeding slash
1233
- if ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) ) {
1234
- $rule = substr( $rule, 1 );
1235
- }
1236
-
1237
- // Escape string for regex
1238
- if ( $context === 'regex' ) {
1239
- $rule = str_replace( '.', '\.', $rule );
1240
- }
1241
-
1242
- // Convert any existing wildcards
1243
- if ( $wildcard !== '*' && strpos( $rule, '*' ) !== false ) {
1244
- $rule = str_replace( '*', $wildcard, $rule );
1245
- }
1246
-
1247
- // Wrap directory fragments and files in wildcards for zip
1248
- if ( $context === 'zip' && ( $fragment || $file ) ) {
1249
- $rule = $wildcard . $rule . $wildcard;
1250
- }
1251
-
1252
- // Add a wildcard to the end of absolute url for zips
1253
- if ( $context === 'zip' && $absolute ) {
1254
- $rule .= $wildcard;
1255
- }
1256
-
1257
- // Add and end carrot to files for pclzip but only if it doesn't end in a wildcard
1258
- if ( $file && $context === 'regex' ) {
1259
- $rule .= '$';
1260
- }
1261
-
1262
- // Add a start carrot to absolute urls for pclzip
1263
- if ( $absolute && $context === 'regex' ) {
1264
- $rule = '^' . $rule;
1265
- }
1266
-
1267
-
1268
- }
1269
-
1270
- // Escape shell args for zip command
1271
- if ( $context === 'zip' ) {
1272
- $excludes = array_map( 'escapeshellarg', array_unique( $excludes ) );
1273
- }
1274
-
1275
- return implode( $separator, $excludes );
1276
-
1277
- }
1278
-
1279
- /**
1280
- * Add backquotes to tables and db-names in SQL queries. Taken from phpMyAdmin.
1281
- *
1282
- * @param mixed $a_name
1283
- * @return array|string
1284
- */
1285
- private function sql_backquote( $a_name ) {
1286
-
1287
- if ( ! empty( $a_name ) && $a_name !== '*' ) {
1288
-
1289
- if ( is_array( $a_name ) ) {
1290
-
1291
- $result = array();
1292
-
1293
- reset( $a_name );
1294
-
1295
- while ( list( $key, $val ) = each( $a_name ) ) {
1296
- $result[$key] = '`' . $val . '`';
1297
- }
1298
-
1299
- return $result;
1300
-
1301
- }
1302
- else {
1303
-
1304
- return '`' . $a_name . '`';
1305
-
1306
- }
1307
-
1308
- }
1309
- else {
1310
-
1311
- return $a_name;
1312
-
1313
- }
1314
-
1315
- }
1316
-
1317
- /**
1318
- * Reads the Database table in $table and creates
1319
- * SQL Statements for recreating structure and data
1320
- * Taken partially from phpMyAdmin and partially from
1321
- * Alain Wolf, Zurich - Switzerland
1322
- * Website: http://restkultur.ch/personal/wolf/scripts/db_backup/
1323
- *
1324
- * @param string $sql_file
1325
- * @param string $table
1326
- */
1327
- private function make_sql( $sql_file, $table ) {
1328
-
1329
- // Add SQL statement to drop existing table
1330
- $sql_file .= "\n";
1331
- $sql_file .= "\n";
1332
- $sql_file .= "#\n";
1333
- $sql_file .= "# Delete any existing table " . $this->sql_backquote( $table ) . "\n";
1334
- $sql_file .= "#\n";
1335
- $sql_file .= "\n";
1336
- $sql_file .= "DROP TABLE IF EXISTS " . $this->sql_backquote( $table ) . ";\n";
1337
-
1338
- /* Table Structure */
1339
-
1340
- // Comment in SQL-file
1341
- $sql_file .= "\n";
1342
- $sql_file .= "\n";
1343
- $sql_file .= "#\n";
1344
- $sql_file .= "# Table structure of table " . $this->sql_backquote( $table ) . "\n";
1345
- $sql_file .= "#\n";
1346
- $sql_file .= "\n";
1347
-
1348
- // Get table structure
1349
- $query = 'SHOW CREATE TABLE ' . $this->sql_backquote( $table );
1350
- $result = mysql_query( $query, $this->db );
1351
-
1352
- if ( $result ) {
1353
-
1354
- if ( mysql_num_rows( $result ) > 0 ) {
1355
- $sql_create_arr = mysql_fetch_array( $result );
1356
- $sql_file .= $sql_create_arr[1];
1357
- }
1358
-
1359
- mysql_free_result( $result );
1360
- $sql_file .= ' ;';
1361
-
1362
- }
1363
-
1364
- /* Table Contents */
1365
-
1366
- // Get table contents
1367
- $query = 'SELECT * FROM ' . $this->sql_backquote( $table );
1368
- $result = mysql_query( $query, $this->db );
1369
-
1370
- $fields_cnt = 0;
1371
- $rows_cnt = 0;
1372
-
1373
- if ( $result ) {
1374
- $fields_cnt = mysql_num_fields( $result );
1375
- $rows_cnt = mysql_num_rows( $result );
1376
- }
1377
-
1378
- // Comment in SQL-file
1379
- $sql_file .= "\n";
1380
- $sql_file .= "\n";
1381
- $sql_file .= "#\n";
1382
- $sql_file .= "# Data contents of table " . $table . " (" . $rows_cnt . " records)\n";
1383
- $sql_file .= "#\n";
1384
-
1385
- // Checks whether the field is an integer or not
1386
- for ( $j = 0; $j < $fields_cnt; $j ++ ) {
1387
-
1388
- $field_set[$j] = $this->sql_backquote( mysql_field_name( $result, $j ) );
1389
- $type = mysql_field_type( $result, $j );
1390
-
1391
- if ( $type === 'tinyint' || $type === 'smallint' || $type === 'mediumint' || $type === 'int' || $type === 'bigint' )
1392
- $field_num[$j] = true;
1393
-
1394
- else
1395
- $field_num[$j] = false;
1396
-
1397
- }
1398
-
1399
- // Sets the scheme
1400
- $entries = 'INSERT INTO ' . $this->sql_backquote( $table ) . ' VALUES (';
1401
- $search = array( '\x00', '\x0a', '\x0d', '\x1a' ); //\x08\\x09, not required
1402
- $replace = array( '\0', '\n', '\r', '\Z' );
1403
- $current_row = 0;
1404
- $batch_write = 0;
1405
-
1406
- while ( $row = mysql_fetch_row( $result ) ) {
1407
-
1408
- $current_row ++;
1409
-
1410
- // build the statement
1411
- for ( $j = 0; $j < $fields_cnt; $j ++ ) {
1412
-
1413
- if ( ! isset( $row[$j] ) ) {
1414
- $values[] = 'NULL';
1415
-
1416
- }
1417
- elseif ( $row[$j] === '0' || $row[$j] !== '' ) {
1418
-
1419
- // a number
1420
- if ( $field_num[$j] )
1421
- $values[] = $row[$j];
1422
-
1423
- else
1424
- $values[] = "'" . str_replace( $search, $replace, $this->sql_addslashes( $row[$j] ) ) . "'";
1425
-
1426
- }
1427
- else {
1428
- $values[] = "''";
1429
-
1430
- }
1431
-
1432
- }
1433
-
1434
- $sql_file .= " \n" . $entries . implode( ', ', $values ) . ") ;";
1435
-
1436
- // write the rows in batches of 100
1437
- if ( $batch_write === 100 ) {
1438
- $batch_write = 0;
1439
- $this->write_sql( $sql_file );
1440
- $sql_file = '';
1441
- }
1442
-
1443
- $batch_write ++;
1444
-
1445
- unset( $values );
1446
-
1447
- }
1448
-
1449
- mysql_free_result( $result );
1450
-
1451
- // Create footer/closing comment in SQL-file
1452
- $sql_file .= "\n";
1453
- $sql_file .= "#\n";
1454
- $sql_file .= "# End of data contents of table " . $table . "\n";
1455
- $sql_file .= "# --------------------------------------------------------\n";
1456
- $sql_file .= "\n";
1457
-
1458
- $this->write_sql( $sql_file );
1459
-
1460
- }
1461
-
1462
- /**
1463
- * Better addslashes for SQL queries.
1464
- * Taken from phpMyAdmin.
1465
- *
1466
- * @param string $a_string (default: '')
1467
- * @param bool $is_like (default: false)
1468
- * @return mixed
1469
- */
1470
- private function sql_addslashes( $a_string = '', $is_like = false ) {
1471
-
1472
- if ( $is_like )
1473
- $a_string = str_replace( '\\', '\\\\\\\\', $a_string );
1474
-
1475
- else
1476
- $a_string = str_replace( '\\', '\\\\', $a_string );
1477
-
1478
- $a_string = str_replace( '\'', '\\\'', $a_string );
1479
-
1480
- return $a_string;
1481
- }
1482
-
1483
- /**
1484
- * Write the SQL file
1485
- *
1486
- * @param string $sql
1487
- * @return bool
1488
- */
1489
- private function write_sql( $sql ) {
1490
-
1491
- $sqlname = $this->get_database_dump_filepath();
1492
-
1493
- // Actually write the sql file
1494
- if ( is_writable( $sqlname ) || ! file_exists( $sqlname ) ) {
1495
-
1496
- if ( ! $handle = @fopen( $sqlname, 'a' ) )
1497
- return;
1498
-
1499
- if ( ! fwrite( $handle, $sql ) )
1500
- return;
1501
-
1502
- fclose( $handle );
1503
-
1504
- return true;
1505
-
1506
- }
1507
-
1508
- }
1509
-
1510
- /**
1511
- * Get the errors
1512
- *
1513
- */
1514
- public function get_errors( $context = null ) {
1515
-
1516
- if ( ! empty( $context ) )
1517
- return isset( $this->errors[$context] ) ? $this->errors[$context] : array();
1518
-
1519
- return $this->errors;
1520
-
1521
- }
1522
-
1523
- /**
1524
- * Add an error to the errors stack
1525
- *
1526
- * @param string $context
1527
- * @param mixed $error
1528
- */
1529
- public function error( $context, $error ) {
1530
-
1531
- if ( empty( $context ) || empty( $error ) )
1532
- return;
1533
-
1534
- $this->do_action( 'hmbkp_error' );
1535
-
1536
- $this->errors[$context][$_key = md5( implode( ':', (array) $error ) )] = $error;
1537
-
1538
- }
1539
-
1540
- /**
1541
- * Migrate errors to warnings
1542
- *
1543
- * @param string $context. (default: null)
1544
- */
1545
- private function errors_to_warnings( $context = null ) {
1546
-
1547
- $errors = empty( $context ) ? $this->get_errors() : array( $context => $this->get_errors( $context ) );
1548
-
1549
- if ( empty( $errors ) )
1550
- return;
1551
-
1552
- foreach ( $errors as $error_context => $context_errors ) {
1553
- foreach ( $context_errors as $error ) {
1554
- $this->warning( $error_context, $error );
1555
- }
1556
- }
1557
-
1558
- if ( $context )
1559
- unset( $this->errors[$context] );
1560
-
1561
- else
1562
- $this->errors = array();
1563
-
1564
- }
1565
-
1566
- /**
1567
- * Get the warnings
1568
- *
1569
- */
1570
- public function get_warnings( $context = null ) {
1571
-
1572
- if ( ! empty( $context ) )
1573
- return isset( $this->warnings[$context] ) ? $this->warnings[$context] : array();
1574
-
1575
- return $this->warnings;
1576
-
1577
- }
1578
-
1579
- /**
1580
- * Add an warning to the warnings stack
1581
- *
1582
- * @param string $context
1583
- * @param mixed $warning
1584
- */
1585
- private function warning( $context, $warning ) {
1586
-
1587
- if ( empty( $context ) || empty( $warning ) )
1588
- return;
1589
-
1590
- $this->do_action( 'hmbkp_warning' );
1591
-
1592
- $this->warnings[$context][$_key = md5( implode( ':', (array) $warning ) )] = $warning;
1593
-
1594
- }
1595
-
1596
- /**
1597
- * Custom error handler for catching php errors
1598
- *
1599
- * @param $type
1600
- * @return bool
1601
- */
1602
- public function error_handler( $type ) {
1603
-
1604
- // Skip strict & deprecated warnings
1605
- if ( ( defined( 'E_DEPRECATED' ) && $type === E_DEPRECATED ) || ( defined( 'E_STRICT' ) && $type === E_STRICT ) || error_reporting() === 0 )
1606
- return false;
1607
-
1608
- $args = func_get_args();
1609
-
1610
- array_shift( $args );
1611
-
1612
- $this->warning( 'php', implode( ', ', array_splice( $args, 0, 3 ) ) );
1613
-
1614
- return false;
1615
-
1616
- }
1617
-
1618
- }
1619
-
1620
- /**
1621
- * Add file callback for PclZip, excludes files
1622
- * and sets the database dump to be stored in the root
1623
- * of the zip
1624
- *
1625
- * @param string $event
1626
- * @param array $file
1627
- * @return bool
1628
- */
1629
- function hmbkp_pclzip_callback( $event, $file ) {
1630
-
1631
- global $_hmbkp_exclude_string;
1632
-
1633
- // Don't try to add unreadable files.
1634
- if ( ! is_readable( $file['filename'] ) || ! file_exists( $file['filename'] ) )
1635
- return false;
1636
-
1637
- // Match everything else past the exclude list
1638
- elseif ( $_hmbkp_exclude_string && preg_match( '(' . $_hmbkp_exclude_string . ')', $file['stored_filename'] ) )
1639
- return false;
1640
-
1641
- return true;
1642
-
1643
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/backupwordpress.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the GPL-2.0+.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: BackUpWordPress 3.1.0\n"
6
  "Report-Msgid-Bugs-To: support@humanmade.co.uk\n"
7
- "POT-Creation-Date: 2015-01-13 13:30:57+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -17,55 +17,55 @@ msgstr ""
17
  msgid "The schedule ID was not provided. Aborting."
18
  msgstr ""
19
 
20
- #: admin/actions.php:271
21
  msgid "Backup type cannot be empty"
22
  msgstr ""
23
 
24
- #: admin/actions.php:275
25
  msgid "Invalid backup type"
26
  msgstr ""
27
 
28
- #: admin/actions.php:289
29
  msgid "Schedule cannot be empty"
30
  msgstr ""
31
 
32
- #: admin/actions.php:293
33
  msgid "Invalid schedule"
34
  msgstr ""
35
 
36
- #: admin/actions.php:307
37
  msgid "Day of the week must be a valid lowercase day name"
38
  msgstr ""
39
 
40
- #: admin/actions.php:326
41
  msgid "Day of month must be between 1 and 31"
42
  msgstr ""
43
 
44
- #: admin/actions.php:345
45
  msgid "Hours must be between 0 and 23"
46
  msgstr ""
47
 
48
- #: admin/actions.php:364
49
  msgid "Minutes must be between 0 and 59"
50
  msgstr ""
51
 
52
- #: admin/actions.php:378
53
  msgid "Max backups can't be empty"
54
  msgstr ""
55
 
56
- #: admin/actions.php:382
57
  msgid "Max backups must be a number"
58
  msgstr ""
59
 
60
- #: admin/actions.php:386
61
  msgid "Max backups must be greater than 0"
62
  msgstr ""
63
 
64
- #: admin/actions.php:743 admin/actions.php:749
65
  msgid "BackUpWordPress has detected a problem."
66
  msgstr ""
67
 
68
- #: admin/actions.php:743 admin/actions.php:749
69
  msgid ""
70
  "%1$s is returning a %2$s response which could mean cron jobs aren't getting "
71
  "fired properly. BackUpWordPress relies on wp-cron to run scheduled backups. "
@@ -116,7 +116,7 @@ msgstr ""
116
 
117
  #: admin/constants.php:14 admin/constants.php:30 admin/constants.php:46
118
  #: admin/constants.php:62 admin/constants.php:78 admin/constants.php:94
119
- #: admin/constants.php:110 classes/class-email.php:58
120
  msgid "You've set it to: %s"
121
  msgstr ""
122
 
@@ -128,7 +128,7 @@ msgstr ""
128
 
129
  #: admin/constants.php:17 admin/constants.php:33 admin/constants.php:49
130
  #: admin/constants.php:65 admin/constants.php:81 admin/constants.php:97
131
- #: admin/constants.php:113 classes/class-email.php:61
132
  msgid "e.g."
133
  msgstr ""
134
 
@@ -474,11 +474,11 @@ msgid "Exclude &rarr;"
474
  msgstr ""
475
 
476
  #: admin/schedule-form-excludes.php:345 admin/schedule-form.php:185
477
- #: admin/schedule-settings.php:79
478
  msgid "Done"
479
  msgstr ""
480
 
481
- #: admin/schedule-form.php:1 admin/schedule-settings.php:7
482
  msgid "Settings"
483
  msgstr ""
484
 
@@ -602,59 +602,59 @@ msgstr ""
602
  msgid "on the %1$s of each month at %2$s"
603
  msgstr ""
604
 
605
- #: admin/schedule-sentence.php:59
606
  msgid "manually"
607
  msgstr ""
608
 
609
- #: admin/schedule-sentence.php:69
610
  msgid "this server"
611
  msgstr ""
612
 
613
- #: admin/schedule-sentence.php:77
614
  msgid "store the most recent backup in %s"
615
  msgstr ""
616
 
617
- #: admin/schedule-sentence.php:83
618
  msgid "don't store any backups in on this server"
619
  msgstr ""
620
 
621
- #: admin/schedule-sentence.php:89
622
  msgid "store the last %1$s backups in %2$s"
623
  msgstr ""
624
 
625
- #: admin/schedule-sentence.php:120
626
  msgid "%s. "
627
  msgstr ""
628
 
629
- #: admin/schedule-sentence.php:124
630
  msgid "Send a copy of each backup to %s."
631
  msgstr ""
632
 
633
- #: admin/schedule-sentence.php:152
634
  msgid "Backups will be compressed and should be smaller than this."
635
  msgstr ""
636
 
637
- #: admin/schedule-sentence.php:154
638
  msgid "this shouldn't take long&hellip;"
639
  msgstr ""
640
 
641
- #: admin/schedule-sentence.php:154
642
  msgid "calculating the size of your backup&hellip;"
643
  msgstr ""
644
 
645
- #: admin/schedule-settings.php:5
646
  msgid "Run now"
647
  msgstr ""
648
 
649
- #: admin/schedule-settings.php:13
650
  msgid "Excludes"
651
  msgstr ""
652
 
653
- #: admin/schedule-settings.php:25 functions/interface.php:34
654
  msgid "Delete"
655
  msgstr ""
656
 
657
- #: admin/server-info.php:41
658
  msgid "%1$s - %2$s"
659
  msgstr ""
660
 
@@ -668,205 +668,257 @@ msgid ""
668
  "Destinations &amp; Unlimited Sites)%4$s"
669
  msgstr ""
670
 
671
- #: backupwordpress.php:243
672
  msgid "Update"
673
  msgstr ""
674
 
675
- #: backupwordpress.php:244
676
  msgid "Cancel"
677
  msgstr ""
678
 
679
- #: backupwordpress.php:245
680
  msgid ""
681
  "Are you sure you want to delete this schedule? All of it's backups will "
682
  "also be deleted."
683
  msgstr ""
684
 
685
- #: backupwordpress.php:245 backupwordpress.php:246 backupwordpress.php:247
686
- #: backupwordpress.php:248
687
  msgid "'Cancel' to go back, 'OK' to delete."
688
  msgstr ""
689
 
690
- #: backupwordpress.php:246
691
  msgid "Are you sure you want to delete this backup?"
692
  msgstr ""
693
 
694
- #: backupwordpress.php:247
695
  msgid "Are you sure you want to remove this exclude rule?"
696
  msgstr ""
697
 
698
- #: backupwordpress.php:248
699
  msgid ""
700
  "Reducing the number of backups that are stored on this server will cause "
701
  "some of your existing backups to be deleted, are you sure that's what you "
702
  "want?"
703
  msgstr ""
704
 
705
- #: classes/class-email.php:26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
706
  msgid "Email notification"
707
  msgstr ""
708
 
709
- #: classes/class-email.php:32
710
  msgid ""
711
  "Receive a notification email when a backup completes, if the backup is "
712
  "small enough (&lt; %s) then it will be attached to the email. Separate "
713
  "multiple email addresses with a comma."
714
  msgstr ""
715
 
716
- #: classes/class-email.php:61
717
  msgid ""
718
  "The maximum filesize of your backup that will be attached to your "
719
  "notification emails . Defaults to %s."
720
  msgstr ""
721
 
722
- #: classes/class-email.php:80
723
  msgid "Send an email notification to %s"
724
  msgstr ""
725
 
726
- #: classes/class-email.php:115
727
  msgid "%s isn't a valid email"
728
  msgstr ""
729
 
730
- #: classes/class-email.php:175 classes/class-webhooks.php:58
731
  msgid "Backup of %s Failed"
732
  msgstr ""
733
 
734
- #: classes/class-email.php:177
735
  msgid "BackUpWordPress was unable to backup your site %1$s."
736
  msgstr ""
737
 
738
- #: classes/class-email.php:177
739
  msgid "Here are the errors that we're encountered:"
740
  msgstr ""
741
 
742
- #: classes/class-email.php:177
743
  msgid ""
744
  "If the errors above look like Martian, forward this email to %3$s and we'll "
745
  "take a look"
746
  msgstr ""
747
 
748
- #: classes/class-email.php:177
749
  msgid ""
750
  "Kind Regards,\n"
751
  "The Apologetic BackUpWordPress Backup Emailing Robot"
752
  msgstr ""
753
 
754
- #: classes/class-email.php:185
755
  msgid "Backup of %s"
756
  msgstr ""
757
 
758
- #: classes/class-email.php:190 classes/class-email.php:199
759
  msgid "BackUpWordPress has completed a backup of your site %1$s."
760
  msgstr ""
761
 
762
- #: classes/class-email.php:190
763
  msgid "The backup file should be attached to this email."
764
  msgstr ""
765
 
766
- #: classes/class-email.php:190 classes/class-email.php:199
767
  msgid "You can download the backup file by clicking the link below:"
768
  msgstr ""
769
 
770
- #: classes/class-email.php:190 classes/class-email.php:199
771
  msgid ""
772
  "Kind Regards,\n"
773
  "The Happy BackUpWordPress Backup Emailing Robot"
774
  msgstr ""
775
 
776
- #: classes/class-email.php:199
777
  msgid "Unfortunately the backup file was too large to attach to this email."
778
  msgstr ""
779
 
780
- #: classes/class-hmbkp-path.php:254
781
  msgid "This %s file ensures that other people cannot download your backup files."
782
  msgstr ""
783
 
784
- #: classes/class-requirements.php:626
785
- msgid "Schedule: %s"
786
- msgstr ""
787
-
788
- #: classes/class-requirements.php:626
789
- msgid "Duration: %s"
790
- msgstr ""
791
-
792
  #: classes/class-schedule.php:137
793
  msgid "Invalid Option Name"
794
  msgstr ""
795
 
796
- #: classes/class-schedule.php:257
797
  msgid "Argument 1 for %s must be a valid integer"
798
  msgstr ""
799
 
800
- #: classes/class-schedule.php:612
801
  msgid "Argument 1 for %s must be a valid future timestamp"
802
  msgstr ""
803
 
804
- #: classes/class-schedule.php:650
805
  msgid "Argument 1 for %s must be a valid cron reoccurrence or \"manually\""
806
  msgstr ""
807
 
808
- #: classes/class-schedule.php:785 functions/interface.php:244
809
  msgid "Starting Backup"
810
  msgstr ""
811
 
812
- #: classes/class-schedule.php:865
813
  msgid "Error writing to file. (%s)"
814
  msgstr ""
815
 
816
- #: classes/class-schedule.php:911
817
  msgid "Dumping Database %s"
818
  msgstr ""
819
 
820
- #: classes/class-schedule.php:916
821
  msgid "Verifying Database Dump %s"
822
  msgstr ""
823
 
824
- #: classes/class-schedule.php:921
825
  msgid "Creating zip archive %s"
826
  msgstr ""
827
 
828
- #: classes/class-schedule.php:926
829
  msgid "Verifying Zip Archive %s"
830
  msgstr ""
831
 
832
- #: classes/class-schedule.php:931
833
  msgid "Finishing Backup"
834
  msgstr ""
835
 
836
- #: classes/class-schedule.php:1042
 
 
 
 
837
  #. translators: min=minute
838
  msgid "%s min"
839
  msgid_plural "%s mins"
840
  msgstr[0] ""
841
  msgstr[1] ""
842
 
843
- #: classes/class-schedule.php:1052
844
  msgid "%s hour"
845
  msgid_plural "%s hours"
846
  msgstr[0] ""
847
  msgstr[1] ""
848
 
849
- #: classes/class-schedule.php:1115
850
  msgid "Argument 1 for %s must be a non empty string"
851
  msgstr ""
852
 
853
- #: classes/class-schedule.php:1120
854
  msgid "%s doesn't exist"
855
  msgstr ""
856
 
857
- #: classes/class-schedule.php:1125
858
  msgid "That backup wasn't created by this schedule"
859
  msgstr ""
860
 
861
- #: classes/class-services.php:278
862
  msgid "Argument 1 for %s must be a valid filepath"
863
  msgstr ""
864
 
865
- #: classes/class-services.php:293
866
  msgid "Argument 1 for %s must be a registered service"
867
  msgstr ""
868
 
869
- #: classes/class-services.php:310
870
  msgid "Argument 1 for %s must be a valid class"
871
  msgstr ""
872
 
@@ -874,75 +926,51 @@ msgstr ""
874
  msgid "BackUpWordPress"
875
  msgstr ""
876
 
877
- #: classes/class-setup.php:154
878
  msgid ""
879
  "BackUpWordPress requires PHP version %1$s or later and WordPress version "
880
  "%2$s or later to run. It has not been activated. %3$s%4$s%5$sLearn more%6$s"
881
  msgstr ""
882
 
883
- #: classes/class-webhooks.php:102
884
  msgid "Error: %s"
885
  msgstr ""
886
 
887
- #: classes/wp-cli.php:43
888
- msgid "Backup: Dumping database..."
889
- msgstr ""
890
-
891
- #: classes/wp-cli.php:47
892
- msgid "Backup: Zipping everything up..."
893
- msgstr ""
894
-
895
- #: classes/wp-cli.php:65
896
- msgid "Invalid backup path"
897
- msgstr ""
898
-
899
- #: classes/wp-cli.php:71
900
- msgid "Invalid root path"
901
- msgstr ""
902
-
903
- #: classes/wp-cli.php:99
904
- msgid "Backup Complete: "
905
- msgstr ""
906
-
907
- #: classes/wp-cli.php:101
908
- msgid "Backup Failed"
909
- msgstr ""
910
-
911
- #: functions/core.php:207
912
  msgid "BackUpWordPress has setup your default schedules."
913
  msgstr ""
914
 
915
- #: functions/core.php:207
916
  msgid ""
917
  "By default BackUpWordPress performs a daily backup of your database and a "
918
  "weekly backup of your database &amp; files. You can modify these schedules."
919
  msgstr ""
920
 
921
- #: functions/core.php:224
922
  msgid "Once Hourly"
923
  msgstr ""
924
 
925
- #: functions/core.php:225
926
  msgid "Twice Daily"
927
  msgstr ""
928
 
929
- #: functions/core.php:226
930
  msgid "Once Daily"
931
  msgstr ""
932
 
933
- #: functions/core.php:227
934
  msgid "Once Weekly"
935
  msgstr ""
936
 
937
- #: functions/core.php:228
938
  msgid "Once Biweekly"
939
  msgstr ""
940
 
941
- #: functions/core.php:229
942
  msgid "Once Monthly"
943
  msgstr ""
944
 
945
- #: functions/core.php:247
946
  msgid "You can only delete directories inside your WordPress installation"
947
  msgstr ""
948
 
@@ -958,200 +986,170 @@ msgstr ""
958
  msgid "Dismiss"
959
  msgstr ""
960
 
961
- #: functions/interface.php:119
962
  msgid ""
963
  "The backups directory can't be created because your %1$s directory isn't "
964
  "writable, run %2$s or %3$s or create the folder yourself."
965
  msgstr ""
966
 
967
- #: functions/interface.php:123
968
  msgid ""
969
  "Your backups directory isn't writable, run %1$s or %2$s or set the "
970
  "permissions yourself."
971
  msgstr ""
972
 
973
- #: functions/interface.php:127
974
  msgid ""
975
  "%1$s is running in %2$s, please contact your host and ask them to disable "
976
  "it. BackUpWordPress may not work correctly whilst %3$s is on."
977
  msgstr ""
978
 
979
- #: functions/interface.php:127
980
  msgid "http://php.net/manual/en/features.safe-mode.php"
981
  msgstr ""
982
 
983
- #: functions/interface.php:127
984
  msgid "Safe Mode"
985
  msgstr ""
986
 
987
- #: functions/interface.php:135
988
  msgid "Your custom path does not exist"
989
  msgstr ""
990
 
991
- #: functions/interface.php:139
992
  msgid ""
993
  "Your custom path is unreachable due to a restriction set in your PHP "
994
  "configuration (open_basedir)"
995
  msgstr ""
996
 
997
- #: functions/interface.php:144
998
  msgid ""
999
  "Your custom backups directory %1$s doesn't exist and can't be created, your "
1000
  "backups will be saved to %2$s instead."
1001
  msgstr ""
1002
 
1003
- #: functions/interface.php:148
1004
  msgid ""
1005
  "Your custom backups directory %1$s isn't writable, new backups will be "
1006
  "saved to %2$s instead."
1007
  msgstr ""
1008
 
1009
- #: functions/interface.php:157
1010
  msgid "Your site root path %s isn't readable."
1011
  msgstr ""
1012
 
1013
- #: functions/interface.php:217
1014
  msgid "Database and Files"
1015
  msgstr ""
1016
 
1017
- #: functions/interface.php:220
1018
  msgid "Files"
1019
  msgstr ""
1020
 
1021
- #: functions/interface.php:223
1022
  msgid "Database"
1023
  msgstr ""
1024
 
1025
- #: functions/interface.php:228
1026
  msgid "Legacy"
1027
  msgstr ""
1028
 
1029
- #: functions/interface.php:243
1030
  msgid "Started %s ago"
1031
  msgstr ""
1032
 
1033
- #: functions/interface.php:245
1034
  msgid "cancel"
1035
  msgstr ""
1036
 
1037
- #: functions/interface.php:291
1038
  msgid "No backups completed"
1039
  msgstr ""
1040
 
1041
- #: functions/interface.php:303
1042
  msgid "Complete Hourly"
1043
  msgstr ""
1044
 
1045
- #: functions/interface.php:304
1046
  msgid "File Hourly"
1047
  msgstr ""
1048
 
1049
- #: functions/interface.php:305
1050
  msgid "Database Hourly"
1051
  msgstr ""
1052
 
1053
- #: functions/interface.php:306
1054
  msgid "Complete Twicedaily"
1055
  msgstr ""
1056
 
1057
- #: functions/interface.php:307
1058
  msgid "File Twicedaily"
1059
  msgstr ""
1060
 
1061
- #: functions/interface.php:308
1062
  msgid "Database Twicedaily"
1063
  msgstr ""
1064
 
1065
- #: functions/interface.php:309
1066
  msgid "Complete Daily"
1067
  msgstr ""
1068
 
1069
- #: functions/interface.php:310
1070
  msgid "File Daily"
1071
  msgstr ""
1072
 
1073
- #: functions/interface.php:311
1074
  msgid "Database Daily"
1075
  msgstr ""
1076
 
1077
- #: functions/interface.php:312
1078
  msgid "Complete Weekly"
1079
  msgstr ""
1080
 
1081
- #: functions/interface.php:313
1082
  msgid "File Weekly"
1083
  msgstr ""
1084
 
1085
- #: functions/interface.php:314
1086
  msgid "Database Weekly"
1087
  msgstr ""
1088
 
1089
- #: functions/interface.php:315
1090
  msgid "Complete Biweekly"
1091
  msgstr ""
1092
 
1093
- #: functions/interface.php:316
1094
  msgid "File Biweekly"
1095
  msgstr ""
1096
 
1097
- #: functions/interface.php:317
1098
  msgid "Database Biweekly"
1099
  msgstr ""
1100
 
1101
- #: functions/interface.php:318
1102
  msgid "Complete Monthly"
1103
  msgstr ""
1104
 
1105
- #: functions/interface.php:319
1106
  msgid "File Monthly"
1107
  msgstr ""
1108
 
1109
- #: functions/interface.php:320
1110
  msgid "Database Monthly"
1111
  msgstr ""
1112
 
1113
- #: functions/interface.php:321
1114
  msgid "Complete Manually"
1115
  msgstr ""
1116
 
1117
- #: functions/interface.php:322
1118
  msgid "File Manually"
1119
  msgstr ""
1120
 
1121
- #: functions/interface.php:323
1122
  msgid "Database Manually"
1123
  msgstr ""
1124
 
1125
- #: hm-backup/hm-backup.php:286
1126
- msgid "archive filename must be a non empty string"
1127
- msgstr ""
1128
-
1129
- #: hm-backup/hm-backup.php:289
1130
- msgid "invalid file extension for archive filename <code>%s</code>"
1131
- msgstr ""
1132
-
1133
- #: hm-backup/hm-backup.php:329
1134
- msgid "database dump filename must be a non empty string"
1135
- msgstr ""
1136
-
1137
- #: hm-backup/hm-backup.php:332
1138
- msgid "invalid file extension for database dump filename <code>%s</code>"
1139
- msgstr ""
1140
-
1141
- #: hm-backup/hm-backup.php:363
1142
- msgid "Invalid root path <code>%s</code> must be a valid directory path"
1143
- msgstr ""
1144
-
1145
- #: hm-backup/hm-backup.php:392
1146
- msgid "Invalid backup path <code>%s</code> must be a non empty (string)"
1147
- msgstr ""
1148
-
1149
- #: hm-backup/hm-backup.php:444
1150
- msgid ""
1151
- "Invalid backup type <code>%s</code> must be one of (string) file, database "
1152
- "or complete"
1153
- msgstr ""
1154
-
1155
  #. Plugin URI of the plugin/theme
1156
  msgid "http://bwp.hmn.md/"
1157
  msgstr ""
@@ -1171,14 +1169,14 @@ msgstr ""
1171
  msgid "http://hmn.md/"
1172
  msgstr ""
1173
 
1174
- #: admin/schedule-sentence.php:117
1175
  msgctxt ""
1176
  "1: Backup Type 2: Total size of backup 3: Schedule 4: Number of backups to "
1177
  "store"
1178
  msgid "Backup my %1$s %2$s %3$s, %4$s."
1179
  msgstr ""
1180
 
1181
- #: functions/interface.php:293
1182
  msgctxt "backups count"
1183
  msgid "One backup completed"
1184
  msgid_plural "%1$s backups completed"
2
  # This file is distributed under the GPL-2.0+.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: BackUpWordPress 3.1.2\n"
6
  "Report-Msgid-Bugs-To: support@humanmade.co.uk\n"
7
+ "POT-Creation-Date: 2015-02-03 16:38:07+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
17
  msgid "The schedule ID was not provided. Aborting."
18
  msgstr ""
19
 
20
+ #: admin/actions.php:269
21
  msgid "Backup type cannot be empty"
22
  msgstr ""
23
 
24
+ #: admin/actions.php:273
25
  msgid "Invalid backup type"
26
  msgstr ""
27
 
28
+ #: admin/actions.php:287
29
  msgid "Schedule cannot be empty"
30
  msgstr ""
31
 
32
+ #: admin/actions.php:291
33
  msgid "Invalid schedule"
34
  msgstr ""
35
 
36
+ #: admin/actions.php:305
37
  msgid "Day of the week must be a valid lowercase day name"
38
  msgstr ""
39
 
40
+ #: admin/actions.php:324
41
  msgid "Day of month must be between 1 and 31"
42
  msgstr ""
43
 
44
+ #: admin/actions.php:343
45
  msgid "Hours must be between 0 and 23"
46
  msgstr ""
47
 
48
+ #: admin/actions.php:362
49
  msgid "Minutes must be between 0 and 59"
50
  msgstr ""
51
 
52
+ #: admin/actions.php:376
53
  msgid "Max backups can't be empty"
54
  msgstr ""
55
 
56
+ #: admin/actions.php:380
57
  msgid "Max backups must be a number"
58
  msgstr ""
59
 
60
+ #: admin/actions.php:384
61
  msgid "Max backups must be greater than 0"
62
  msgstr ""
63
 
64
+ #: admin/actions.php:736 admin/actions.php:742
65
  msgid "BackUpWordPress has detected a problem."
66
  msgstr ""
67
 
68
+ #: admin/actions.php:736 admin/actions.php:742
69
  msgid ""
70
  "%1$s is returning a %2$s response which could mean cron jobs aren't getting "
71
  "fired properly. BackUpWordPress relies on wp-cron to run scheduled backups. "
116
 
117
  #: admin/constants.php:14 admin/constants.php:30 admin/constants.php:46
118
  #: admin/constants.php:62 admin/constants.php:78 admin/constants.php:94
119
+ #: admin/constants.php:110 classes/class-email-service.php:60
120
  msgid "You've set it to: %s"
121
  msgstr ""
122
 
128
 
129
  #: admin/constants.php:17 admin/constants.php:33 admin/constants.php:49
130
  #: admin/constants.php:65 admin/constants.php:81 admin/constants.php:97
131
+ #: admin/constants.php:113 classes/class-email-service.php:63
132
  msgid "e.g."
133
  msgstr ""
134
 
474
  msgstr ""
475
 
476
  #: admin/schedule-form-excludes.php:345 admin/schedule-form.php:185
477
+ #: admin/schedule-settings.php:81
478
  msgid "Done"
479
  msgstr ""
480
 
481
+ #: admin/schedule-form.php:1 admin/schedule-settings.php:9
482
  msgid "Settings"
483
  msgstr ""
484
 
602
  msgid "on the %1$s of each month at %2$s"
603
  msgstr ""
604
 
605
+ #: admin/schedule-sentence.php:59 admin/schedule-sentence.php:65
606
  msgid "manually"
607
  msgstr ""
608
 
609
+ #: admin/schedule-sentence.php:70
610
  msgid "this server"
611
  msgstr ""
612
 
613
+ #: admin/schedule-sentence.php:78
614
  msgid "store the most recent backup in %s"
615
  msgstr ""
616
 
617
+ #: admin/schedule-sentence.php:84
618
  msgid "don't store any backups in on this server"
619
  msgstr ""
620
 
621
+ #: admin/schedule-sentence.php:90
622
  msgid "store the last %1$s backups in %2$s"
623
  msgstr ""
624
 
625
+ #: admin/schedule-sentence.php:121
626
  msgid "%s. "
627
  msgstr ""
628
 
629
+ #: admin/schedule-sentence.php:125
630
  msgid "Send a copy of each backup to %s."
631
  msgstr ""
632
 
633
+ #: admin/schedule-sentence.php:153
634
  msgid "Backups will be compressed and should be smaller than this."
635
  msgstr ""
636
 
637
+ #: admin/schedule-sentence.php:155
638
  msgid "this shouldn't take long&hellip;"
639
  msgstr ""
640
 
641
+ #: admin/schedule-sentence.php:155
642
  msgid "calculating the size of your backup&hellip;"
643
  msgstr ""
644
 
645
+ #: admin/schedule-settings.php:7
646
  msgid "Run now"
647
  msgstr ""
648
 
649
+ #: admin/schedule-settings.php:15
650
  msgid "Excludes"
651
  msgstr ""
652
 
653
+ #: admin/schedule-settings.php:27 functions/interface.php:34
654
  msgid "Delete"
655
  msgstr ""
656
 
657
+ #: admin/server-info.php:43
658
  msgid "%1$s - %2$s"
659
  msgstr ""
660
 
668
  "Destinations &amp; Unlimited Sites)%4$s"
669
  msgstr ""
670
 
671
+ #: backupwordpress.php:238
672
  msgid "Update"
673
  msgstr ""
674
 
675
+ #: backupwordpress.php:239
676
  msgid "Cancel"
677
  msgstr ""
678
 
679
+ #: backupwordpress.php:240
680
  msgid ""
681
  "Are you sure you want to delete this schedule? All of it's backups will "
682
  "also be deleted."
683
  msgstr ""
684
 
685
+ #: backupwordpress.php:240 backupwordpress.php:241 backupwordpress.php:242
686
+ #: backupwordpress.php:243
687
  msgid "'Cancel' to go back, 'OK' to delete."
688
  msgstr ""
689
 
690
+ #: backupwordpress.php:241
691
  msgid "Are you sure you want to delete this backup?"
692
  msgstr ""
693
 
694
+ #: backupwordpress.php:242
695
  msgid "Are you sure you want to remove this exclude rule?"
696
  msgstr ""
697
 
698
+ #: backupwordpress.php:243
699
  msgid ""
700
  "Reducing the number of backups that are stored on this server will cause "
701
  "some of your existing backups to be deleted, are you sure that's what you "
702
  "want?"
703
  msgstr ""
704
 
705
+ #: classes/class-backup.php:348
706
+ msgid "archive filename must be a non empty string"
707
+ msgstr ""
708
+
709
+ #: classes/class-backup.php:352
710
+ msgid "invalid file extension for archive filename <code>%s</code>"
711
+ msgstr ""
712
+
713
+ #: classes/class-backup.php:392
714
+ msgid "database dump filename must be a non empty string"
715
+ msgstr ""
716
+
717
+ #: classes/class-backup.php:396
718
+ msgid "invalid file extension for database dump filename <code>%s</code>"
719
+ msgstr ""
720
+
721
+ #: classes/class-backup.php:429
722
+ msgid "Invalid root path <code>%s</code> must be a valid directory path"
723
+ msgstr ""
724
+
725
+ #: classes/class-backup.php:454
726
+ msgid ""
727
+ "Invalid existing archive filepath <code>%s</code> must be a non empty "
728
+ "(string)"
729
+ msgstr ""
730
+
731
+ #: classes/class-backup.php:508
732
+ msgid ""
733
+ "Invalid backup type <code>%s</code> must be one of (string) file, database "
734
+ "or complete"
735
+ msgstr ""
736
+
737
+ #: classes/class-backupwordpress-wp-cli-command.php:50
738
+ msgid "Backup: Dumping database..."
739
+ msgstr ""
740
+
741
+ #: classes/class-backupwordpress-wp-cli-command.php:54
742
+ msgid "Backup: Zipping everything up..."
743
+ msgstr ""
744
+
745
+ #: classes/class-backupwordpress-wp-cli-command.php:70
746
+ msgid "Invalid backup path"
747
+ msgstr ""
748
+
749
+ #: classes/class-backupwordpress-wp-cli-command.php:75
750
+ msgid "Invalid root path"
751
+ msgstr ""
752
+
753
+ #: classes/class-backupwordpress-wp-cli-command.php:106
754
+ msgid "Backup Complete: "
755
+ msgstr ""
756
+
757
+ #: classes/class-backupwordpress-wp-cli-command.php:108
758
+ msgid "Backup Failed"
759
+ msgstr ""
760
+
761
+ #: classes/class-email-service.php:28
762
  msgid "Email notification"
763
  msgstr ""
764
 
765
+ #: classes/class-email-service.php:34
766
  msgid ""
767
  "Receive a notification email when a backup completes, if the backup is "
768
  "small enough (&lt; %s) then it will be attached to the email. Separate "
769
  "multiple email addresses with a comma."
770
  msgstr ""
771
 
772
+ #: classes/class-email-service.php:63
773
  msgid ""
774
  "The maximum filesize of your backup that will be attached to your "
775
  "notification emails . Defaults to %s."
776
  msgstr ""
777
 
778
+ #: classes/class-email-service.php:82
779
  msgid "Send an email notification to %s"
780
  msgstr ""
781
 
782
+ #: classes/class-email-service.php:117
783
  msgid "%s isn't a valid email"
784
  msgstr ""
785
 
786
+ #: classes/class-email-service.php:179 classes/class-webhook-service.php:59
787
  msgid "Backup of %s Failed"
788
  msgstr ""
789
 
790
+ #: classes/class-email-service.php:181
791
  msgid "BackUpWordPress was unable to backup your site %1$s."
792
  msgstr ""
793
 
794
+ #: classes/class-email-service.php:181
795
  msgid "Here are the errors that we're encountered:"
796
  msgstr ""
797
 
798
+ #: classes/class-email-service.php:181
799
  msgid ""
800
  "If the errors above look like Martian, forward this email to %3$s and we'll "
801
  "take a look"
802
  msgstr ""
803
 
804
+ #: classes/class-email-service.php:181
805
  msgid ""
806
  "Kind Regards,\n"
807
  "The Apologetic BackUpWordPress Backup Emailing Robot"
808
  msgstr ""
809
 
810
+ #: classes/class-email-service.php:189
811
  msgid "Backup of %s"
812
  msgstr ""
813
 
814
+ #: classes/class-email-service.php:194 classes/class-email-service.php:203
815
  msgid "BackUpWordPress has completed a backup of your site %1$s."
816
  msgstr ""
817
 
818
+ #: classes/class-email-service.php:194
819
  msgid "The backup file should be attached to this email."
820
  msgstr ""
821
 
822
+ #: classes/class-email-service.php:194 classes/class-email-service.php:203
823
  msgid "You can download the backup file by clicking the link below:"
824
  msgstr ""
825
 
826
+ #: classes/class-email-service.php:194 classes/class-email-service.php:203
827
  msgid ""
828
  "Kind Regards,\n"
829
  "The Happy BackUpWordPress Backup Emailing Robot"
830
  msgstr ""
831
 
832
+ #: classes/class-email-service.php:203
833
  msgid "Unfortunately the backup file was too large to attach to this email."
834
  msgstr ""
835
 
836
+ #: classes/class-path.php:249
837
  msgid "This %s file ensures that other people cannot download your backup files."
838
  msgstr ""
839
 
 
 
 
 
 
 
 
 
840
  #: classes/class-schedule.php:137
841
  msgid "Invalid Option Name"
842
  msgstr ""
843
 
844
+ #: classes/class-schedule.php:250
845
  msgid "Argument 1 for %s must be a valid integer"
846
  msgstr ""
847
 
848
+ #: classes/class-schedule.php:599
849
  msgid "Argument 1 for %s must be a valid future timestamp"
850
  msgstr ""
851
 
852
+ #: classes/class-schedule.php:636
853
  msgid "Argument 1 for %s must be a valid cron reoccurrence or \"manually\""
854
  msgstr ""
855
 
856
+ #: classes/class-schedule.php:765 functions/interface.php:249
857
  msgid "Starting Backup"
858
  msgstr ""
859
 
860
+ #: classes/class-schedule.php:851
861
  msgid "Error writing to file. (%s)"
862
  msgstr ""
863
 
864
+ #: classes/class-schedule.php:899
865
  msgid "Dumping Database %s"
866
  msgstr ""
867
 
868
+ #: classes/class-schedule.php:904
869
  msgid "Verifying Database Dump %s"
870
  msgstr ""
871
 
872
+ #: classes/class-schedule.php:909
873
  msgid "Creating zip archive %s"
874
  msgstr ""
875
 
876
+ #: classes/class-schedule.php:914
877
  msgid "Verifying Zip Archive %s"
878
  msgstr ""
879
 
880
+ #: classes/class-schedule.php:919
881
  msgid "Finishing Backup"
882
  msgstr ""
883
 
884
+ #: classes/class-schedule.php:970
885
+ msgid "An unexpected error occured"
886
+ msgstr ""
887
+
888
+ #: classes/class-schedule.php:1033
889
  #. translators: min=minute
890
  msgid "%s min"
891
  msgid_plural "%s mins"
892
  msgstr[0] ""
893
  msgstr[1] ""
894
 
895
+ #: classes/class-schedule.php:1043
896
  msgid "%s hour"
897
  msgid_plural "%s hours"
898
  msgstr[0] ""
899
  msgstr[1] ""
900
 
901
+ #: classes/class-schedule.php:1105
902
  msgid "Argument 1 for %s must be a non empty string"
903
  msgstr ""
904
 
905
+ #: classes/class-schedule.php:1110
906
  msgid "%s doesn't exist"
907
  msgstr ""
908
 
909
+ #: classes/class-schedule.php:1115
910
  msgid "That backup wasn't created by this schedule"
911
  msgstr ""
912
 
913
+ #: classes/class-services.php:81
914
  msgid "Argument 1 for %s must be a valid filepath"
915
  msgstr ""
916
 
917
+ #: classes/class-services.php:97
918
  msgid "Argument 1 for %s must be a registered service"
919
  msgstr ""
920
 
921
+ #: classes/class-services.php:115
922
  msgid "Argument 1 for %s must be a valid class"
923
  msgstr ""
924
 
926
  msgid "BackUpWordPress"
927
  msgstr ""
928
 
929
+ #: classes/class-setup.php:141
930
  msgid ""
931
  "BackUpWordPress requires PHP version %1$s or later and WordPress version "
932
  "%2$s or later to run. It has not been activated. %3$s%4$s%5$sLearn more%6$s"
933
  msgstr ""
934
 
935
+ #: classes/class-webhook-service.php:103
936
  msgid "Error: %s"
937
  msgstr ""
938
 
939
+ #: functions/core.php:218
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
940
  msgid "BackUpWordPress has setup your default schedules."
941
  msgstr ""
942
 
943
+ #: functions/core.php:218
944
  msgid ""
945
  "By default BackUpWordPress performs a daily backup of your database and a "
946
  "weekly backup of your database &amp; files. You can modify these schedules."
947
  msgstr ""
948
 
949
+ #: functions/core.php:233
950
  msgid "Once Hourly"
951
  msgstr ""
952
 
953
+ #: functions/core.php:234
954
  msgid "Twice Daily"
955
  msgstr ""
956
 
957
+ #: functions/core.php:235
958
  msgid "Once Daily"
959
  msgstr ""
960
 
961
+ #: functions/core.php:236
962
  msgid "Once Weekly"
963
  msgstr ""
964
 
965
+ #: functions/core.php:237
966
  msgid "Once Biweekly"
967
  msgstr ""
968
 
969
+ #: functions/core.php:238
970
  msgid "Once Monthly"
971
  msgstr ""
972
 
973
+ #: functions/core.php:256
974
  msgid "You can only delete directories inside your WordPress installation"
975
  msgstr ""
976
 
986
  msgid "Dismiss"
987
  msgstr ""
988
 
989
+ #: functions/interface.php:120
990
  msgid ""
991
  "The backups directory can't be created because your %1$s directory isn't "
992
  "writable, run %2$s or %3$s or create the folder yourself."
993
  msgstr ""
994
 
995
+ #: functions/interface.php:124
996
  msgid ""
997
  "Your backups directory isn't writable, run %1$s or %2$s or set the "
998
  "permissions yourself."
999
  msgstr ""
1000
 
1001
+ #: functions/interface.php:128
1002
  msgid ""
1003
  "%1$s is running in %2$s, please contact your host and ask them to disable "
1004
  "it. BackUpWordPress may not work correctly whilst %3$s is on."
1005
  msgstr ""
1006
 
1007
+ #: functions/interface.php:128
1008
  msgid "http://php.net/manual/en/features.safe-mode.php"
1009
  msgstr ""
1010
 
1011
+ #: functions/interface.php:128
1012
  msgid "Safe Mode"
1013
  msgstr ""
1014
 
1015
+ #: functions/interface.php:136
1016
  msgid "Your custom path does not exist"
1017
  msgstr ""
1018
 
1019
+ #: functions/interface.php:140
1020
  msgid ""
1021
  "Your custom path is unreachable due to a restriction set in your PHP "
1022
  "configuration (open_basedir)"
1023
  msgstr ""
1024
 
1025
+ #: functions/interface.php:145
1026
  msgid ""
1027
  "Your custom backups directory %1$s doesn't exist and can't be created, your "
1028
  "backups will be saved to %2$s instead."
1029
  msgstr ""
1030
 
1031
+ #: functions/interface.php:149
1032
  msgid ""
1033
  "Your custom backups directory %1$s isn't writable, new backups will be "
1034
  "saved to %2$s instead."
1035
  msgstr ""
1036
 
1037
+ #: functions/interface.php:158
1038
  msgid "Your site root path %s isn't readable."
1039
  msgstr ""
1040
 
1041
+ #: functions/interface.php:218
1042
  msgid "Database and Files"
1043
  msgstr ""
1044
 
1045
+ #: functions/interface.php:222
1046
  msgid "Files"
1047
  msgstr ""
1048
 
1049
+ #: functions/interface.php:226
1050
  msgid "Database"
1051
  msgstr ""
1052
 
1053
+ #: functions/interface.php:233
1054
  msgid "Legacy"
1055
  msgstr ""
1056
 
1057
+ #: functions/interface.php:248
1058
  msgid "Started %s ago"
1059
  msgstr ""
1060
 
1061
+ #: functions/interface.php:250
1062
  msgid "cancel"
1063
  msgstr ""
1064
 
1065
+ #: functions/interface.php:298
1066
  msgid "No backups completed"
1067
  msgstr ""
1068
 
1069
+ #: functions/interface.php:309
1070
  msgid "Complete Hourly"
1071
  msgstr ""
1072
 
1073
+ #: functions/interface.php:310
1074
  msgid "File Hourly"
1075
  msgstr ""
1076
 
1077
+ #: functions/interface.php:311
1078
  msgid "Database Hourly"
1079
  msgstr ""
1080
 
1081
+ #: functions/interface.php:312
1082
  msgid "Complete Twicedaily"
1083
  msgstr ""
1084
 
1085
+ #: functions/interface.php:313
1086
  msgid "File Twicedaily"
1087
  msgstr ""
1088
 
1089
+ #: functions/interface.php:314
1090
  msgid "Database Twicedaily"
1091
  msgstr ""
1092
 
1093
+ #: functions/interface.php:315
1094
  msgid "Complete Daily"
1095
  msgstr ""
1096
 
1097
+ #: functions/interface.php:316
1098
  msgid "File Daily"
1099
  msgstr ""
1100
 
1101
+ #: functions/interface.php:317
1102
  msgid "Database Daily"
1103
  msgstr ""
1104
 
1105
+ #: functions/interface.php:318
1106
  msgid "Complete Weekly"
1107
  msgstr ""
1108
 
1109
+ #: functions/interface.php:319
1110
  msgid "File Weekly"
1111
  msgstr ""
1112
 
1113
+ #: functions/interface.php:320
1114
  msgid "Database Weekly"
1115
  msgstr ""
1116
 
1117
+ #: functions/interface.php:321
1118
  msgid "Complete Biweekly"
1119
  msgstr ""
1120
 
1121
+ #: functions/interface.php:322
1122
  msgid "File Biweekly"
1123
  msgstr ""
1124
 
1125
+ #: functions/interface.php:323
1126
  msgid "Database Biweekly"
1127
  msgstr ""
1128
 
1129
+ #: functions/interface.php:324
1130
  msgid "Complete Monthly"
1131
  msgstr ""
1132
 
1133
+ #: functions/interface.php:325
1134
  msgid "File Monthly"
1135
  msgstr ""
1136
 
1137
+ #: functions/interface.php:326
1138
  msgid "Database Monthly"
1139
  msgstr ""
1140
 
1141
+ #: functions/interface.php:327
1142
  msgid "Complete Manually"
1143
  msgstr ""
1144
 
1145
+ #: functions/interface.php:328
1146
  msgid "File Manually"
1147
  msgstr ""
1148
 
1149
+ #: functions/interface.php:329
1150
  msgid "Database Manually"
1151
  msgstr ""
1152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1153
  #. Plugin URI of the plugin/theme
1154
  msgid "http://bwp.hmn.md/"
1155
  msgstr ""
1169
  msgid "http://hmn.md/"
1170
  msgstr ""
1171
 
1172
+ #: admin/schedule-sentence.php:118
1173
  msgctxt ""
1174
  "1: Backup Type 2: Total size of backup 3: Schedule 4: Number of backups to "
1175
  "store"
1176
  msgid "Backup my %1$s %2$s %3$s, %4$s."
1177
  msgstr ""
1178
 
1179
+ #: functions/interface.php:300
1180
  msgctxt "backups count"
1181
  msgid "One backup completed"
1182
  msgid_plural "%1$s backups completed"
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: humanmade, willmot, pauldewouters, joehoyle, mattheu, tcrsavage, c
3
  Tags: back up, backup, backups, database, zip, db, files, archive, wp-cli, humanmade
4
  Requires at least: 3.9
5
  Tested up to: 4.2-alpha
6
- Stable tag: 3.1.1
7
 
8
  Simple automated backups of your WordPress powered website.
9
 
@@ -132,6 +132,49 @@ You can also tweet <a href="http://twitter.com/humanmadeltd">@humanmadeltd</a> o
132
 
133
  == Changelog ==
134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  #### 3.1.0 / 2015-01-13
136
 
137
  * Correct $response1 variable
3
  Tags: back up, backup, backups, database, zip, db, files, archive, wp-cli, humanmade
4
  Requires at least: 3.9
5
  Tested up to: 4.2-alpha
6
+ Stable tag: 3.1.2
7
 
8
  Simple automated backups of your WordPress powered website.
9
 
132
 
133
  == Changelog ==
134
 
135
+ ### 3.1.2 / 2015-02-03
136
+
137
+ * (simplify-bwp-file-timestamp) Simplify the file name timestamp
138
+ * Fix class file name
139
+ * (fixup-setup-class) Add missing transients to uninstall routine
140
+ * switch Travis notifications to Slack instead of Hipchat
141
+ * Do not delete backups on uninstall
142
+ * wrap in parenthesis
143
+ * Fix include paths after moving uninstall to own file herpderp
144
+ * Update BackUp class include
145
+ * Add all cases to switch
146
+ * Pass scanned files sizes through conform_dir()
147
+ * Fix some classes and requires
148
+ * (origin/issue-684, issue-684) Fix namespaces
149
+ * Remove unnecessary wildcard from regex
150
+ * (crazy-refactor) Remove some duplication
151
+ * Formatting
152
+ * Fix Class name
153
+ * Blank line
154
+ * Uses a DirectoryIterator to delete files
155
+ * Remove tests for now
156
+ * Fix stable tag number
157
+ * Revert to using uninstall.php
158
+ * Add tests for uninstall and deactivate
159
+ * Remove double lie break
160
+ * Remove double line break
161
+ * Remove phpdocumentor
162
+ * We still need to require some scripts...
163
+ * We dont need to check for this constant in the hook callback
164
+ * Use get_col to directly have an array of schedule option names
165
+ * Remove namespacing
166
+ * Remove debugging
167
+ * Make the uninstall, activation and deactivation hooks work
168
+ * (change-singleton-implementation) Change the singleton implementation to not use the static() function
169
+ * path argument interfers with wp-cli path argument.
170
+ * Fix some scrutinizer issues, mostly major ones
171
+ * Consistent default name for database dumps
172
+ * Major 5.3 re-factoring fun
173
+ * Minor code formatting
174
+ * else if should be elseif
175
+ * Update the WP_CLI command to fix some issues
176
+ * Add support for copying and updating an existing backups
177
+
178
  #### 3.1.0 / 2015-01-13
179
 
180
  * Correct $response1 variable
uninstall.php CHANGED
@@ -1,52 +1,27 @@
1
  <?php
2
 
3
  if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
4
- return;
5
  }
6
 
7
  if ( ! current_user_can( 'activate_plugins' ) ) {
8
- return;
9
  }
10
 
11
- if ( ! defined( 'HMBKP_REQUIRED_WP_VERSION' ) ) {
12
- define( 'HMBKP_REQUIRED_WP_VERSION', '3.8.4' );
13
- }
14
-
15
- // Don't activate on old versions of WordPress
16
- global $wp_version;
17
-
18
- if ( version_compare( $wp_version, HMBKP_REQUIRED_WP_VERSION, '<' ) ) {
19
- return;
20
- }
21
-
22
- if ( ! defined( 'HMBKP_PLUGIN_PATH' ) ) {
23
- define( 'HMBKP_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
24
- }
25
 
26
- // Load the schedules
27
- require_once( HMBKP_PLUGIN_PATH . 'hm-backup/hm-backup.php' );
28
- require_once( HMBKP_PLUGIN_PATH . 'classes/class-services.php' );
29
- require_once( HMBKP_PLUGIN_PATH . 'classes/class-hmbkp-path.php' );
30
- require_once( HMBKP_PLUGIN_PATH . 'classes/class-schedule.php' );
31
- require_once( HMBKP_PLUGIN_PATH . 'classes/class-schedules.php' );
32
- require_once( HMBKP_PLUGIN_PATH . 'functions/core.php' );
33
 
34
- $schedules = HMBKP_Schedules::get_instance();
35
 
36
- // Cancel all the schedules and delete all the backups
37
- foreach ( $schedules->get_schedules() as $schedule ) {
38
- $schedule->cancel( true );
39
- }
40
 
41
- // Remove the backups directory
42
- hmbkp_rmdirtree( hmbkp_path() );
43
 
44
- // Remove all the options
45
- foreach ( array( 'hmbkp_enable_support', 'hmbkp_plugin_version', 'hmbkp_path', 'hmbkp_default_path', 'hmbkp_upsell' ) as $option ) {
46
- delete_option( $option );
47
- }
48
 
49
  // Delete all transients
50
- foreach ( array( 'hmbkp_plugin_data', 'hmbkp_directory_filesizes', 'hmbkp_directory_filesize_running' ) as $transient ) {
51
- delete_transient( $transient );
52
- }
1
  <?php
2
 
3
  if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
4
+ exit;
5
  }
6
 
7
  if ( ! current_user_can( 'activate_plugins' ) ) {
8
+ exit;
9
  }
10
 
11
+ global $wpdb;
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
+ // Get all schedule options with a SELECT query and delete them.
14
+ $schedules = $wpdb->get_col( $wpdb->prepare( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE %s", 'hmbkp_schedule_%' ) );
 
 
 
 
 
15
 
16
+ array_map( 'delete_option', $schedules );
17
 
18
+ // Remove all the options
 
 
 
19
 
20
+ $options = array( 'hmbkp_enable_support', 'hmbkp_plugin_version', 'hmbkp_path', 'hmbkp_default_path', 'hmbkp_upsell' );
 
21
 
22
+ array_map( 'delete_option', $options );
 
 
 
23
 
24
  // Delete all transients
25
+ $transients = array( 'hmbkp_plugin_data', 'hmbkp_directory_filesizes', 'hmbkp_directory_filesize_running', 'timeout_hmbkp_wp_cron_test_beacon', 'hmbkp_wp_cron_test_beacon' );
26
+
27
+ array_map( 'delete_transient', $transients );