BackUpWordPress - Version 3.6.0

Version Description

= 3.4 =

  • This version introduces a major refactoring of the code responsible for the core backup engine. We made sure to write unit tests for the new code, and we have tested it on several user's sites. It fixes a lot of old bugs, and Windows users should see major improvements to reliability.

= 3.3.4 =

  • WordPress 4.4 compatibility.

= 3.3.1 =

  • Fixes a bug that would prevent downloading backups since 3.3.0 - please update.

= 3.2.5 =

  • Security fixes related to add_query_arg

= 3.2.1 =

  • Important bug fixes. Please upgrade to this version to avoid incomplete or broken backups.

= 3.1.3 =

  • Fixes backwards compatibility for add-ons and avoids a Fatal Error. Please upgrade straight to this version before upgrading your add-ons.

= 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.6.0
Comparing to
See all releases

Code changes from version 3.5 to 3.6.0

Files changed (118) hide show
  1. admin/actions.php +34 -85
  2. admin/backups-table.php +6 -6
  3. admin/constants.php +2 -2
  4. admin/enable-support.php +1 -1
  5. admin/extensions.php +165 -0
  6. admin/faq.php +28 -28
  7. admin/menu.php +23 -12
  8. admin/page.php +7 -3
  9. admin/schedule-form-excludes.php +59 -67
  10. admin/schedule-form.php +8 -8
  11. admin/schedule-sentence.php +4 -12
  12. admin/schedule-settings.php +16 -21
  13. admin/server-info.php +2 -2
  14. admin/upsell.php +10 -19
  15. assets/hmbkp.css +5 -0
  16. assets/hmbkp.js +10 -1
  17. assets/hmbkp.min.css +1 -1
  18. assets/hmbkp.min.js +1 -1
  19. backupwordpress.php +1 -3
  20. classes/backup/class-backup-engine-database-imysqldump.php +2 -5
  21. classes/backup/class-backup-engine-file-zip-archive.php +3 -5
  22. classes/backup/class-backup-engine-file.php +1 -1
  23. classes/backup/class-backup-engine.php +3 -4
  24. classes/backup/class-backup-status.php +107 -108
  25. classes/backup/class-backup.php +25 -15
  26. classes/class-backupwordpress-wp-cli-command.php +1 -2
  27. classes/class-email-service.php +10 -14
  28. classes/class-excludes.php +13 -13
  29. classes/class-extensions.php +107 -0
  30. classes/class-notices.php +96 -33
  31. classes/class-path.php +4 -7
  32. classes/class-plugin.php +48 -5
  33. classes/class-requirements.php +1 -2
  34. classes/class-scheduled-backup.php +7 -10
  35. classes/class-schedules.php +0 -1
  36. classes/class-service.php +0 -3
  37. classes/class-services.php +4 -4
  38. classes/class-setup.php +1 -4
  39. classes/class-webhook-service.php +12 -11
  40. classes/class-wpremote-webhook-service.php +0 -1
  41. composer.lock +11 -11
  42. functions/core.php +26 -36
  43. functions/interface.php +37 -10
  44. languages/backupwordpress.pot +233 -149
  45. readme.txt +15 -6
  46. uninstall.php +5 -3
  47. vendor/composer/installed.json +12 -12
  48. vendor/symfony/finder/Adapter/AbstractAdapter.php +0 -0
  49. vendor/symfony/finder/Adapter/AbstractFindAdapter.php +0 -0
  50. vendor/symfony/finder/Adapter/AdapterInterface.php +0 -0
  51. vendor/symfony/finder/Adapter/BsdFindAdapter.php +0 -0
  52. vendor/symfony/finder/Adapter/GnuFindAdapter.php +0 -0
  53. vendor/symfony/finder/Adapter/PhpAdapter.php +0 -0
  54. vendor/symfony/finder/CHANGELOG.md +0 -0
  55. vendor/symfony/finder/Comparator/Comparator.php +0 -0
  56. vendor/symfony/finder/Comparator/DateComparator.php +0 -0
  57. vendor/symfony/finder/Comparator/NumberComparator.php +0 -0
  58. vendor/symfony/finder/Exception/AccessDeniedException.php +0 -0
  59. vendor/symfony/finder/Exception/AdapterFailureException.php +0 -0
  60. vendor/symfony/finder/Exception/ExceptionInterface.php +0 -0
  61. vendor/symfony/finder/Exception/OperationNotPermitedException.php +0 -0
  62. vendor/symfony/finder/Exception/ShellCommandFailureException.php +0 -0
  63. vendor/symfony/finder/Expression/Expression.php +0 -0
  64. vendor/symfony/finder/Expression/Glob.php +0 -0
  65. vendor/symfony/finder/Expression/Regex.php +0 -0
  66. vendor/symfony/finder/Expression/ValueInterface.php +0 -0
  67. vendor/symfony/finder/Finder.php +0 -0
  68. vendor/symfony/finder/Glob.php +0 -0
  69. vendor/symfony/finder/Iterator/CustomFilterIterator.php +0 -0
  70. vendor/symfony/finder/Iterator/DateRangeFilterIterator.php +0 -0
  71. vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php +0 -0
  72. vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php +0 -0
  73. vendor/symfony/finder/Iterator/FilePathsIterator.php +0 -0
  74. vendor/symfony/finder/Iterator/FileTypeFilterIterator.php +0 -0
  75. vendor/symfony/finder/Iterator/FilecontentFilterIterator.php +0 -0
  76. vendor/symfony/finder/Iterator/FilenameFilterIterator.php +0 -0
  77. vendor/symfony/finder/Iterator/FilterIterator.php +9 -2
  78. vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php +0 -0
  79. vendor/symfony/finder/Iterator/PathFilterIterator.php +0 -0
  80. vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php +0 -0
  81. vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php +0 -0
  82. vendor/symfony/finder/Iterator/SortableIterator.php +0 -0
  83. vendor/symfony/finder/LICENSE +0 -0
  84. vendor/symfony/finder/Shell/Command.php +0 -0
  85. vendor/symfony/finder/Shell/Shell.php +0 -0
  86. vendor/symfony/finder/SplFileInfo.php +0 -0
  87. vendor/symfony/finder/composer.json +0 -0
  88. vendor/symfony/finder/phpunit.xml.dist +0 -0
  89. vendor/symfony/process/CHANGELOG.md +0 -0
  90. vendor/symfony/process/Exception/ExceptionInterface.php +0 -0
  91. vendor/symfony/process/Exception/InvalidArgumentException.php +0 -0
  92. vendor/symfony/process/Exception/LogicException.php +0 -0
  93. vendor/symfony/process/Exception/ProcessFailedException.php +0 -0
  94. vendor/symfony/process/Exception/ProcessTimedOutException.php +0 -0
  95. vendor/symfony/process/Exception/RuntimeException.php +0 -0
  96. vendor/symfony/process/ExecutableFinder.php +0 -0
  97. vendor/symfony/process/LICENSE +0 -0
  98. vendor/symfony/process/PhpExecutableFinder.php +0 -0
  99. vendor/symfony/process/PhpProcess.php +0 -0
  100. vendor/symfony/process/Pipes/AbstractPipes.php +71 -0
  101. vendor/symfony/process/Pipes/PipesInterface.php +0 -0
  102. vendor/symfony/process/Pipes/UnixPipes.php +15 -71
  103. vendor/symfony/process/Pipes/WindowsPipes.php +20 -93
  104. vendor/symfony/process/Process.php +26 -28
  105. vendor/symfony/process/ProcessBuilder.php +0 -0
  106. vendor/symfony/process/ProcessUtils.php +0 -0
  107. vendor/symfony/process/Tests/ExecutableFinderTest.php +0 -0
  108. vendor/symfony/process/Tests/NonStopableProcess.php +0 -0
  109. vendor/symfony/process/Tests/PhpExecutableFinderTest.php +0 -0
  110. vendor/symfony/process/Tests/PhpProcessTest.php +0 -0
  111. vendor/symfony/process/Tests/PipeStdinInStdoutStdErrStreamSelect.php +0 -0
  112. vendor/symfony/process/Tests/ProcessBuilderTest.php +0 -0
  113. vendor/symfony/process/Tests/ProcessFailedExceptionTest.php +0 -0
  114. vendor/symfony/process/Tests/ProcessTest.php +32 -13
  115. vendor/symfony/process/Tests/ProcessUtilsTest.php +0 -0
  116. vendor/symfony/process/Tests/SignalListener.php +0 -0
  117. vendor/symfony/process/composer.json +0 -0
  118. vendor/symfony/process/phpunit.xml.dist +0 -0
admin/actions.php CHANGED
@@ -81,6 +81,14 @@ function request_do_backup() {
81
 
82
  $schedule_id = sanitize_text_field( urldecode( $_REQUEST['hmbkp_schedule_id'] ) );
83
  $task = new \HM\Backdrop\Task( '\HM\BackUpWordPress\run_schedule_async', $schedule_id );
 
 
 
 
 
 
 
 
84
  $task->schedule();
85
 
86
  die;
@@ -191,7 +199,7 @@ function edit_schedule_services_submit() {
191
 
192
  $schedule->save();
193
 
194
- if ( $errors ) {
195
  foreach ( $errors as $error ) {
196
  add_settings_error( $error );
197
  }
@@ -199,7 +207,7 @@ function edit_schedule_services_submit() {
199
 
200
  $redirect = remove_query_arg( array( 'hmbkp_panel', 'action' ), wp_get_referer() );
201
 
202
- if ( $errors ) {
203
  $redirect = wp_get_referer();
204
  }
205
 
@@ -223,6 +231,7 @@ function edit_schedule_submit() {
223
  }
224
 
225
  $schedule = new Scheduled_Backup( sanitize_text_field( $_POST['hmbkp_schedule_id'] ) );
 
226
 
227
  $errors = array();
228
 
@@ -234,16 +243,11 @@ function edit_schedule_submit() {
234
 
235
  if ( ! trim( $schedule_type ) ) {
236
  $errors['hmbkp_schedule_type'] = __( 'Backup type cannot be empty', 'backupwordpress' );
237
- }
238
-
239
- elseif ( ! in_array( $schedule_type, array( 'complete', 'file', 'database' ) ) ) {
240
  $errors['hmbkp_schedule_type'] = __( 'Invalid backup type', 'backupwordpress' );
241
- }
242
-
243
- else {
244
  $settings['type'] = $schedule_type;
245
  }
246
-
247
  }
248
 
249
  if ( isset( $_POST['hmbkp_schedule_recurrence']['hmbkp_type'] ) ) {
@@ -252,16 +256,11 @@ function edit_schedule_submit() {
252
 
253
  if ( empty( $schedule_recurrence_type ) ) {
254
  $errors['hmbkp_schedule_recurrence']['hmbkp_type'] = __( 'Schedule cannot be empty', 'backupwordpress' );
255
- }
256
-
257
- elseif ( ! in_array( $schedule_recurrence_type, array_keys( cron_schedules() ) ) && 'manually' !== $schedule_recurrence_type ) {
258
  $errors['hmbkp_schedule_recurrence']['hmbkp_type'] = __( 'Invalid schedule', 'backupwordpress' );
259
- }
260
-
261
- else {
262
  $settings['recurrence'] = $schedule_recurrence_type;
263
  }
264
-
265
  }
266
 
267
  if ( isset( $_POST['hmbkp_schedule_recurrence']['hmbkp_schedule_start_day_of_week'] ) ) {
@@ -270,12 +269,9 @@ function edit_schedule_submit() {
270
 
271
  if ( ! in_array( $day_of_week, array( 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ) ) ) {
272
  $errors['hmbkp_schedule_start_day_of_week'] = __( 'Day of the week must be a valid, lowercase day name', 'backupwordpress' );
273
- }
274
-
275
- else {
276
  $settings['start_time']['day_of_week'] = $day_of_week;
277
  }
278
-
279
  }
280
 
281
  if ( ( 'monthly' === $schedule_recurrence_type ) && isset( $_POST['hmbkp_schedule_recurrence']['hmbkp_schedule_start_day_of_month'] ) ) {
@@ -289,12 +285,9 @@ function edit_schedule_submit() {
289
 
290
  if ( false === filter_var( $day_of_month, FILTER_VALIDATE_INT, array( 'options' => $options ) ) ) {
291
  $errors['hmbkp_schedule_start_day_of_month'] = __( 'Day of month must be between 1 and 31', 'backupwordpress' );
292
- }
293
-
294
- else {
295
  $settings['start_time']['day_of_month'] = $day_of_month;
296
  }
297
-
298
  }
299
 
300
  if ( isset( $_POST['hmbkp_schedule_recurrence']['hmbkp_schedule_start_hours'] ) ) {
@@ -303,17 +296,14 @@ function edit_schedule_submit() {
303
 
304
  $options = array(
305
  'min_range' => 0,
306
- 'max_range' => 23
307
  );
308
 
309
  if ( false === filter_var( $hours, FILTER_VALIDATE_INT, array( 'options' => $options ) ) ) {
310
  $errors['hmbkp_schedule_start_hours'] = __( 'Hours must be between 0 and 23', 'backupwordpress' );
311
- }
312
-
313
- else {
314
  $settings['start_time']['hours'] = $hours;
315
  }
316
-
317
  }
318
 
319
  if ( isset( $_POST['hmbkp_schedule_recurrence']['hmbkp_schedule_start_minutes'] ) ) {
@@ -327,12 +317,9 @@ function edit_schedule_submit() {
327
 
328
  if ( false === filter_var( $minutes, FILTER_VALIDATE_INT, array( 'options' => $options ) ) ) {
329
  $errors['hmbkp_schedule_start_minutes'] = __( 'Minutes must be between 0 and 59', 'backupwordpress' );
330
- }
331
-
332
- else {
333
  $settings['start_time']['minutes'] = $minutes;
334
  }
335
-
336
  }
337
 
338
  if ( isset( $_POST['hmbkp_schedule_max_backups'] ) ) {
@@ -341,20 +328,15 @@ function edit_schedule_submit() {
341
 
342
  if ( empty( $max_backups ) ) {
343
  $errors['hmbkp_schedule_max_backups'] = __( 'Max backups can\'t be empty', 'backupwordpress' );
344
- }
345
-
346
- elseif ( ! is_numeric( $max_backups ) ) {
347
  $errors['hmbkp_schedule_max_backups'] = __( 'Max backups must be a number', 'backupwordpress' );
348
- }
349
-
350
- elseif ( ! ( $max_backups >= 1 ) ) {
351
  $errors['hmbkp_schedule_max_backups'] = __( 'Max backups must be greater than 0', 'backupwordpress' );
352
- }
353
-
354
- else {
355
  $settings['max_backups'] = absint( $max_backups );
356
  }
357
-
358
  }
359
 
360
  // Save the service options
@@ -370,7 +352,6 @@ function edit_schedule_submit() {
370
  if ( $start_time ) {
371
  $schedule->set_schedule_start_time( $start_time );
372
  }
373
-
374
  }
375
 
376
  if ( ! empty( $settings['recurrence'] ) ) {
@@ -392,11 +373,9 @@ function edit_schedule_submit() {
392
  $schedule->delete_old_backups();
393
 
394
  if ( $errors ) {
395
-
396
  foreach ( $errors as $error ) {
397
  add_settings_error( $error );
398
  }
399
-
400
  }
401
 
402
  $redirect = remove_query_arg( array( 'hmbkp_panel', 'action' ), wp_get_referer() );
@@ -481,7 +460,7 @@ function recalculate_directory_filesize() {
481
  }
482
 
483
  // Delete the cached directory size
484
- delete_transient( 'hmbkp_directory_filesizes' );
485
 
486
  $url = add_query_arg( array( 'action' => 'hmbkp_edit_schedule', 'hmbkp_panel' => 'hmbkp_edit_schedule_excludes' ), get_settings_url() );
487
 
@@ -530,7 +509,6 @@ function heartbeat_received( $response, $data ) {
530
  } else {
531
  $response['hmbkp_schedule_status'] = schedule_status( $schedule, false );
532
  }
533
-
534
  }
535
 
536
  if ( ! empty( $data['hmbkp_client_request'] ) ) {
@@ -550,7 +528,6 @@ function heartbeat_received( $response, $data ) {
550
  $response['heartbeat_interval'] = 'slow';
551
  }
552
  }
553
-
554
  }
555
 
556
  return $response;
@@ -558,42 +535,6 @@ function heartbeat_received( $response, $data ) {
558
  }
559
  add_filter( 'heartbeat_received', 'HM\BackUpWordPress\heartbeat_received', 10, 2 );
560
 
561
- // TODO needs work
562
- function display_error_and_offer_to_email_it() {
563
-
564
- check_ajax_referer( 'hmbkp_nonce', 'nonce' );
565
-
566
- if ( empty( $_POST['hmbkp_error'] ) ) {
567
- die;
568
- }
569
-
570
- $errors = explode( "\n", wp_strip_all_tags( stripslashes( $_POST['hmbkp_error'] ) ) );
571
-
572
- Notices::get_instance()->set_notices( 'backup_errors', $errors );
573
-
574
- wp_send_json_success( wp_get_referer() );
575
-
576
- }
577
- add_action( 'wp_ajax_hmbkp_backup_error', 'HM\BackUpWordPress\display_error_and_offer_to_email_it' );
578
-
579
- // TODO needs work
580
- function send_error_via_email() {
581
-
582
- check_ajax_referer( 'hmbkp_nonce', 'nonce' );
583
-
584
- if ( empty( $_POST['hmbkp_error'] ) ) {
585
- die;
586
- }
587
-
588
- $error = wp_strip_all_tags( $_POST['hmbkp_error'] );
589
-
590
- wp_mail( 'backupwordpress@hmn.md', 'BackUpWordPress Fatal error on ' . parse_url( home_url(), PHP_URL_HOST ), $error, 'From: BackUpWordPress <' . get_bloginfo( 'admin_email' ) . '>' . "\r\n" );
591
-
592
- die;
593
-
594
- }
595
- add_action( 'wp_ajax_hmbkp_email_error', 'HM\BackUpWordPress\send_error_via_email' );
596
-
597
  /**
598
  * Load the enable support modal contents
599
  *
@@ -715,3 +656,11 @@ function ajax_cron_test() {
715
 
716
  }
717
  add_action( 'wp_ajax_hmbkp_cron_test', 'HM\BackUpWordPress\ajax_cron_test' );
 
 
 
 
 
 
 
 
81
 
82
  $schedule_id = sanitize_text_field( urldecode( $_REQUEST['hmbkp_schedule_id'] ) );
83
  $task = new \HM\Backdrop\Task( '\HM\BackUpWordPress\run_schedule_async', $schedule_id );
84
+
85
+ /**
86
+ * Backdrop doesn't cleanup tasks which fatal before they can finish
87
+ * so we manually cancel the task if it's already scheduled.
88
+ */
89
+ if ( $task->is_scheduled() ) {
90
+ $task->cancel();
91
+ }
92
  $task->schedule();
93
 
94
  die;
199
 
200
  $schedule->save();
201
 
202
+ if ( ! empty( $errors ) ) {
203
  foreach ( $errors as $error ) {
204
  add_settings_error( $error );
205
  }
207
 
208
  $redirect = remove_query_arg( array( 'hmbkp_panel', 'action' ), wp_get_referer() );
209
 
210
+ if ( ! empty( $errors ) ) {
211
  $redirect = wp_get_referer();
212
  }
213
 
231
  }
232
 
233
  $schedule = new Scheduled_Backup( sanitize_text_field( $_POST['hmbkp_schedule_id'] ) );
234
+ $site_size = new Site_Size( $schedule->get_type(), $schedule->get_excludes() );
235
 
236
  $errors = array();
237
 
243
 
244
  if ( ! trim( $schedule_type ) ) {
245
  $errors['hmbkp_schedule_type'] = __( 'Backup type cannot be empty', 'backupwordpress' );
246
+ } elseif ( ! in_array( $schedule_type, array( 'complete', 'file', 'database' ) ) ) {
 
 
247
  $errors['hmbkp_schedule_type'] = __( 'Invalid backup type', 'backupwordpress' );
248
+ } else {
 
 
249
  $settings['type'] = $schedule_type;
250
  }
 
251
  }
252
 
253
  if ( isset( $_POST['hmbkp_schedule_recurrence']['hmbkp_type'] ) ) {
256
 
257
  if ( empty( $schedule_recurrence_type ) ) {
258
  $errors['hmbkp_schedule_recurrence']['hmbkp_type'] = __( 'Schedule cannot be empty', 'backupwordpress' );
259
+ } elseif ( ! in_array( $schedule_recurrence_type, array_keys( cron_schedules() ) ) && 'manually' !== $schedule_recurrence_type ) {
 
 
260
  $errors['hmbkp_schedule_recurrence']['hmbkp_type'] = __( 'Invalid schedule', 'backupwordpress' );
261
+ } else {
 
 
262
  $settings['recurrence'] = $schedule_recurrence_type;
263
  }
 
264
  }
265
 
266
  if ( isset( $_POST['hmbkp_schedule_recurrence']['hmbkp_schedule_start_day_of_week'] ) ) {
269
 
270
  if ( ! in_array( $day_of_week, array( 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ) ) ) {
271
  $errors['hmbkp_schedule_start_day_of_week'] = __( 'Day of the week must be a valid, lowercase day name', 'backupwordpress' );
272
+ } else {
 
 
273
  $settings['start_time']['day_of_week'] = $day_of_week;
274
  }
 
275
  }
276
 
277
  if ( ( 'monthly' === $schedule_recurrence_type ) && isset( $_POST['hmbkp_schedule_recurrence']['hmbkp_schedule_start_day_of_month'] ) ) {
285
 
286
  if ( false === filter_var( $day_of_month, FILTER_VALIDATE_INT, array( 'options' => $options ) ) ) {
287
  $errors['hmbkp_schedule_start_day_of_month'] = __( 'Day of month must be between 1 and 31', 'backupwordpress' );
288
+ } else {
 
 
289
  $settings['start_time']['day_of_month'] = $day_of_month;
290
  }
 
291
  }
292
 
293
  if ( isset( $_POST['hmbkp_schedule_recurrence']['hmbkp_schedule_start_hours'] ) ) {
296
 
297
  $options = array(
298
  'min_range' => 0,
299
+ 'max_range' => 23,
300
  );
301
 
302
  if ( false === filter_var( $hours, FILTER_VALIDATE_INT, array( 'options' => $options ) ) ) {
303
  $errors['hmbkp_schedule_start_hours'] = __( 'Hours must be between 0 and 23', 'backupwordpress' );
304
+ } else {
 
 
305
  $settings['start_time']['hours'] = $hours;
306
  }
 
307
  }
308
 
309
  if ( isset( $_POST['hmbkp_schedule_recurrence']['hmbkp_schedule_start_minutes'] ) ) {
317
 
318
  if ( false === filter_var( $minutes, FILTER_VALIDATE_INT, array( 'options' => $options ) ) ) {
319
  $errors['hmbkp_schedule_start_minutes'] = __( 'Minutes must be between 0 and 59', 'backupwordpress' );
320
+ } else {
 
 
321
  $settings['start_time']['minutes'] = $minutes;
322
  }
 
323
  }
324
 
325
  if ( isset( $_POST['hmbkp_schedule_max_backups'] ) ) {
328
 
329
  if ( empty( $max_backups ) ) {
330
  $errors['hmbkp_schedule_max_backups'] = __( 'Max backups can\'t be empty', 'backupwordpress' );
331
+ } elseif ( ! is_numeric( $max_backups ) ) {
 
 
332
  $errors['hmbkp_schedule_max_backups'] = __( 'Max backups must be a number', 'backupwordpress' );
333
+ } elseif ( ! ( $max_backups >= 1 ) ) {
 
 
334
  $errors['hmbkp_schedule_max_backups'] = __( 'Max backups must be greater than 0', 'backupwordpress' );
335
+ } elseif ( $site_size->is_site_size_cached() && disk_space_low( $site_size->get_site_size() * $max_backups ) ) {
336
+ $errors['hmbkp_schedule_max_backups'] = sprintf( __( 'Storing %s backups would use %s of disk space but your server only has %s free.', 'backupwordpress' ), '<code>' . number_format_i18n( $max_backups ) . '</code>', '<code>' . size_format( $max_backups * $site_size->get_site_size() ) . '</code>', '<code>' . size_format( disk_free_space( Path::get_path() ) ) . '</code>' );
337
+ } else {
338
  $settings['max_backups'] = absint( $max_backups );
339
  }
 
340
  }
341
 
342
  // Save the service options
352
  if ( $start_time ) {
353
  $schedule->set_schedule_start_time( $start_time );
354
  }
 
355
  }
356
 
357
  if ( ! empty( $settings['recurrence'] ) ) {
373
  $schedule->delete_old_backups();
374
 
375
  if ( $errors ) {
 
376
  foreach ( $errors as $error ) {
377
  add_settings_error( $error );
378
  }
 
379
  }
380
 
381
  $redirect = remove_query_arg( array( 'hmbkp_panel', 'action' ), wp_get_referer() );
460
  }
461
 
462
  // Delete the cached directory size
463
+ @unlink( trailingslashit( Path::get_path() ) . '.files' );
464
 
465
  $url = add_query_arg( array( 'action' => 'hmbkp_edit_schedule', 'hmbkp_panel' => 'hmbkp_edit_schedule_excludes' ), get_settings_url() );
466
 
509
  } else {
510
  $response['hmbkp_schedule_status'] = schedule_status( $schedule, false );
511
  }
 
512
  }
513
 
514
  if ( ! empty( $data['hmbkp_client_request'] ) ) {
528
  $response['heartbeat_interval'] = 'slow';
529
  }
530
  }
 
531
  }
532
 
533
  return $response;
535
  }
536
  add_filter( 'heartbeat_received', 'HM\BackUpWordPress\heartbeat_received', 10, 2 );
537
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
538
  /**
539
  * Load the enable support modal contents
540
  *
656
 
657
  }
658
  add_action( 'wp_ajax_hmbkp_cron_test', 'HM\BackUpWordPress\ajax_cron_test' );
659
+
660
+ /**
661
+ * Remember notice dismissal
662
+ */
663
+ function hmbkp_dismiss_notice() {
664
+ update_site_option( 'hmbkp_hide_info_notice', true );
665
+ }
666
+ add_action( 'wp_ajax_hmbkp_dismiss_notice', 'HM\BackUpWordPress\hmbkp_dismiss_notice' );
admin/backups-table.php CHANGED
@@ -21,11 +21,11 @@ namespace HM\BackUpWordPress;
21
 
22
  <tbody>
23
 
24
- <?php if ( $schedule->get_backups() ) {
25
 
26
  $schedule->delete_old_backups();
27
 
28
- foreach ( $schedule->get_backups() as $file ) {
29
 
30
  if ( ! file_exists( $file ) ) {
31
  continue;
@@ -33,16 +33,16 @@ namespace HM\BackUpWordPress;
33
 
34
  get_backup_row( $file, $schedule );
35
 
36
- }
37
 
38
- } else { ?>
39
 
40
  <tr>
41
  <td class="hmbkp-no-backups" colspan="4"><?php _e( 'This is where your backups will appear once you have some.', 'backupwordpress' ); ?></td>
42
  </tr>
43
 
44
- <?php } ?>
45
 
46
  </tbody>
47
 
48
- </table>
21
 
22
  <tbody>
23
 
24
+ <?php if ( $schedule->get_backups() ) :
25
 
26
  $schedule->delete_old_backups();
27
 
28
+ foreach ( $schedule->get_backups() as $file ) :
29
 
30
  if ( ! file_exists( $file ) ) {
31
  continue;
33
 
34
  get_backup_row( $file, $schedule );
35
 
36
+ endforeach;
37
 
38
+ else : ?>
39
 
40
  <tr>
41
  <td class="hmbkp-no-backups" colspan="4"><?php _e( 'This is where your backups will appear once you have some.', 'backupwordpress' ); ?></td>
42
  </tr>
43
 
44
+ <?php endif; ?>
45
 
46
  </tbody>
47
 
48
+ </table>
admin/constants.php CHANGED
@@ -122,9 +122,9 @@ namespace HM\BackUpWordPress;
122
 
123
  </tr>
124
 
125
- <?php foreach ( Services::get_services() as $file => $service ) {
126
  echo wp_kses_post( call_user_func( array( $service, 'constant' ) ) );
127
- } ?>
128
 
129
  </table>
130
 
122
 
123
  </tr>
124
 
125
+ <?php foreach ( Services::get_services() as $file => $service ) :
126
  echo wp_kses_post( call_user_func( array( $service, 'constant' ) ) );
127
+ endforeach; ?>
128
 
129
  </table>
130
 
admin/enable-support.php CHANGED
@@ -58,4 +58,4 @@
58
  <p class="howto"><?php _e( 'You can disable support in the future by deactivating BackUpWordPress.', 'backupwordpress' ); ?></p>
59
 
60
  <a href="#" class="button-secondary hmbkp-thickbox-close"><?php _e( 'No, thanks', 'backupwordpress' ); ?></a>
61
- <a href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'hmbkp_request_enable_support' ), admin_url( 'admin-post.php' ) ), 'hmbkp_enable_support', 'hmbkp_enable_support_nonce' ) ); ?>" class="button-primary right"><?php _e( 'Yes, I want to enable support', 'backupwordpress' ); ?></a>
58
  <p class="howto"><?php _e( 'You can disable support in the future by deactivating BackUpWordPress.', 'backupwordpress' ); ?></p>
59
 
60
  <a href="#" class="button-secondary hmbkp-thickbox-close"><?php _e( 'No, thanks', 'backupwordpress' ); ?></a>
61
+ <a href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'hmbkp_request_enable_support' ), admin_url( 'admin-post.php' ) ), 'hmbkp_enable_support', 'hmbkp_enable_support_nonce' ) ); ?>" class="button-primary right"><?php _e( 'Yes, I want to enable support', 'backupwordpress' ); ?></a>
admin/extensions.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace HM\BackUpWordPress;
4
+
5
+ ?>
6
+
7
+ <div class="wrap">
8
+
9
+ <h1>
10
+
11
+ <a class="page-title-action" href="<?php echo esc_url( get_settings_url() ); ?>"><?php _e( '&larr; Backups', 'backupwordpress' ); ?></a>
12
+
13
+ <?php _e( 'BackUpWordPress Extensions', 'backupwordpress' ); ?>
14
+
15
+ </h1>
16
+
17
+ <div class="wp-filter">
18
+ <p><?php _e( 'Extend BackUpWordPress by installing extensions. Extensions allows you to pick and choose the exact features you need whilst also supporting us, the developers, so we can continue working on BackUpWordPress.', 'backupwordpress' ); ?></p>
19
+ </div>
20
+
21
+ <?php
22
+ $extensions_data = Extensions::get_instance()->get_edd_data();
23
+
24
+ // Sort by title
25
+ usort( $extensions_data, function( $a, $b ) {
26
+ return strcmp( $b->title->rendered, $a->title->rendered );
27
+ });
28
+
29
+ $installed_plugins = array_reduce( get_plugins(), function( $carry, $item ) {
30
+ $carry[ strtolower( $item['Name'] ) ] = $item['Version'];
31
+ return $carry;
32
+ }, array() );
33
+
34
+ ?>
35
+
36
+ <h3><?php _e( 'Remote Storage', 'backupwordpress' ); ?></h3>
37
+
38
+ <p><?php _e( 'It\'s important to store your backups somewhere other than on your site. Using the extensions below you can easily push your backups to one or more Cloud providers.', 'backupwordpress' ); ?></p>
39
+
40
+ <div class="wp-list-table widefat plugin-install">
41
+
42
+ <div id="the-list">
43
+
44
+ <?php $first = true; ?>
45
+
46
+ <?php foreach ( $extensions_data as $extension ) : ?>
47
+
48
+ <div class="plugin-card plugin-card-<?php echo esc_attr( $extension->slug ); ?>">
49
+
50
+ <div class="plugin-card-top">
51
+
52
+ <div class="name column-name">
53
+
54
+ <h4>
55
+
56
+ <a href="<?php echo esc_url( $extension->link ); ?>" class="thickbox">
57
+
58
+ <?php echo esc_html( $extension->title->rendered ); ?>
59
+
60
+ <img src="<?php echo esc_url( $extension->featured_image_url ); ?>" class="plugin-icon" alt="">
61
+
62
+ </a>
63
+
64
+ </h4>
65
+
66
+ </div>
67
+
68
+ <div class="action-links">
69
+
70
+ <ul class="plugin-action-buttons">
71
+
72
+ <li>
73
+ <?php if ( in_array( strtolower( $extension->title->rendered ), array_keys( $installed_plugins ) ) ) : ?>
74
+
75
+ <span class="button button-disabled" title="<?php _e( 'This extension is already installed', 'backupwordpress' ); ?>"><?php _e( 'Installed', 'backupwordpress' ); ?></span>
76
+
77
+ <?php else : ?>
78
+
79
+ <a class="install-now button-primary" data-slug="<?php echo esc_attr( $extension->slug ); ?>" href="<?php echo esc_url( $extension->link ); ?>" aria-label="Install <?php echo esc_attr( $extension->title->rendered ); ?> now" data-name="<?php echo esc_attr( $extension->title->rendered ); ?>"><?php printf( __( 'Buy Now &dollar;%s', 'backupwordpress' ), $extension->edd_price ); ?></a>
80
+
81
+ <?php endif; ?>
82
+
83
+ </li>
84
+
85
+ <li>
86
+
87
+ <a href="<?php echo esc_url( $extension->link ); ?>" class="thickbox" aria-label="<?php printf( __( 'More information about %s', 'backupwordpress' ), esc_attr( $extension->title->rendered ) ) ; ?>" data-title="<?php echo esc_attr( $extension->title->rendered ); ?>"><?php _e( 'More Details', 'backupwordpress' ); ?></a>
88
+
89
+ </li>
90
+
91
+ </ul>
92
+
93
+ </div>
94
+
95
+ <div class="desc column-description">
96
+
97
+ <p><?php echo wp_kses_post( $extension->content->rendered ); ?></p>
98
+
99
+ </div>
100
+
101
+ </div>
102
+
103
+ <?php
104
+
105
+ $style = $first === true ? 'background-color:aliceblue;' : '';
106
+
107
+ $first = false;
108
+
109
+ ?>
110
+
111
+ <div class="plugin-card-bottom" style="<?php echo esc_attr( $style ); ?>">
112
+
113
+ <div class="vers column-rating">
114
+
115
+ <div>
116
+
117
+ <?php esc_html_e( sprintf( __( 'Plugin version %s', 'backupwordpress' ), $extension->_edd_sl_version ) ); ?>
118
+
119
+ </div>
120
+
121
+ <div>
122
+
123
+ <?php
124
+
125
+ $text = '';
126
+
127
+ if ( in_array( strtolower( $extension->title->rendered ), array_keys( $installed_plugins ) ) ) {
128
+
129
+ $current_version = $installed_plugins[ strtolower( $extension->title->rendered ) ];
130
+
131
+ if ( version_compare( $current_version, $extension->_edd_sl_version, '<' ) ) {
132
+
133
+ $text = sprintf( __( 'A newer version (%1$s) is available. <a href="%2$s">Update now!</a>', 'backupwordpress' ), esc_html( $extension->_edd_sl_version ), esc_url( admin_url( 'update-core.php' ) ) );
134
+ } else {
135
+
136
+ $text = esc_html__( 'You have the latest version', 'backupwordpress' );
137
+
138
+ }
139
+ }
140
+
141
+ echo $text;
142
+
143
+ ?>
144
+
145
+ </div>
146
+
147
+ </div>
148
+
149
+ <div class="column-updated">
150
+
151
+ <strong><?php _e( 'Last Updated:', 'backupwordpress' ); ?></strong> <span title="<?php echo esc_attr( $extension->modified ); ?>"><?php printf( __( '%s ago', 'backupwordpress' ), human_time_diff( strtotime( $extension->modified ) ) ); ?></span>
152
+
153
+ </div>
154
+
155
+ </div>
156
+
157
+ </div>
158
+
159
+ <?php endforeach; ?>
160
+
161
+ </div>
162
+
163
+ </div>
164
+
165
+ </div>
admin/faq.php CHANGED
@@ -1,58 +1,58 @@
1
  <?php
2
  echo '<p><strong>' . __( 'Where does BackUpWordPress store the backup files?', 'backupwordpress' ) . '</strong></p>' .
3
 
4
- '<p>' . __( 'Backups are stored on your server in <code>/wp-content/backups</code>, you can change the directory.', 'backupwordpress' ). '</p>' .
5
 
6
- '<p>' . __( 'Important: By default BackUpWordPress backs up everything in your site root as well as your database, this includes any non WordPress folders that happen to be in your site root. This does mean that your backup directory can get quite large.', 'backupwordpress' ) . '</p>' .
7
 
8
- '<p><strong>' . __( 'What if I want to back up my site to another destination?', 'backupwordpress' ) . '</strong></p>' .
9
 
10
- '<p>' . __( 'BackUpWordPress Pro supports Dropbox, Google Drive, Amazon S3, Rackspace, Azure, DreamObjects and FTP/SFTP. Check it out here: <a href="http://bwp.hmn.md/?utm_source=wordpress-org&utm_medium=plugin-page&utm_campaign=freeplugin" title="BackUpWordPress Homepage" target="_blank">https://bwp.hmn.md</a>', 'backupwordpress' ) . '</p>' .
11
 
12
- '<p><strong>' . __( 'How do I restore my site from a backup?', 'backupwordpress' ) . '</strong></p>' .
13
 
14
- '<p>' . __( 'You need to download the latest backup file either by clicking download on the backups page or via <code>FTP</code>. <code>Unzip</code> the files and upload all the files to your server overwriting your site. You can then import the database using your hosts database management tool (likely <code>phpMyAdmin</code>).', 'backupwordpress' ) . '</p>' .
15
 
16
- '<p>' . __( 'See this guide for more details - <a href="https://bwp.hmn.md/support-center/restore-backup/" title="Go to support center" target="_blank">How to restore from backup</a>.', 'backupwordpress' ) . '</p>' .
17
 
18
- '<p><strong>' . __( 'Does BackUpWordPress back up the backups directory?', 'backupwordpress' ) . '</strong></p>' .
19
 
20
- '<p>' . __( 'No.', 'backupwordpress' ) . '</p>' .
21
 
22
- '<p><strong>' . __( 'I\'m not receiving my backups by email', 'backupwordpress' ) . '</strong></p>' .
23
 
24
- '<p>' . __( 'Most servers have a filesize limit on email attachments, it\'s generally about 10mb. If your backup file is over that limit, it won\'t be sent attached to the email. Instead, you should receive an email with a link to download the backup. If you aren\'t even receiving that, then you likely have a mail issue on your server that you\'ll need to contact your host about.', 'backupwordpress' ) . '</p>' .
25
 
26
- '<p><strong>' . __( 'How many backups are stored by default?', 'backupwordpress' ) . '</strong></p>' .
27
 
28
- '<p>' . __( 'BackUpWordPress stores the last 10 backups by default.', 'backupwordpress' ) . '</p>' .
29
 
30
- '<p><strong>' . __( 'How long should a backup take?', 'backupwordpress' ) . '</strong></p>' .
31
 
32
- '<p>' . __( 'Unless your site is very large (many gigabytes) it should only take a few minutes to perform a backup. If your back up has been running for longer than an hour, it\'s safe to assume that something has gone wrong. Try de-activating and re-activating the plugin. If it keeps happening, contact support.', 'backupwordpress' ) . '</p>' .
33
 
34
- '<p><strong>' . __( 'What do I do if I get the wp-cron error message?', 'backupwordpress' ) . '</strong></p>' .
35
 
36
- '<p>' . __( 'The issue is that your <code>wp-cron.php</code> is not returning a <code>200</code> response when hit with a HTTP request originating from your own server, it could be several things. In most cases, it\'s an issue with the server / site.', 'backupwordpress' ) . '</p>' .
37
 
38
- '<p>' . __( 'There are some things you can test to confirm this is the issue.', 'backupwordpress' ) . '</p>' .
39
 
40
- '<ul><li>' . __( 'Are scheduled posts working? (They use wp-cron as well.)', 'backupwordpress' ) . '</li>' .
41
 
42
- '<li>' . __( 'Are you hosted on Heart Internet? (wp-cron may not be supported by Heart Internet, see below for work-around.)', 'backupwordpress' ) . '</li>' .
43
 
44
- '<li>' . __( 'If you click manual backup, does it work?', 'backupwordpress' ) . '</li>' .
45
 
46
- '<li>' . __( 'Try adding <code>define( \'ALTERNATE_WP_CRON\', true );</code> to your <code>wp-config.php</code>. Do automatic backups work?', 'backupwordpress' ) . '</li>' .
47
 
48
- '<li>' . __( 'Is your site private (i.e. is it behind some kind of authentication, maintenance plugin, .htaccess)? If so, wp-cron won\'t work until you remove it. If you are and you temporarily remove the authentication, do backups start working?', 'backupwordpress' ) . '</li></ul>' .
49
 
50
- '<p>' . __( 'Report the results to our support team for further help. To do this, either enable support from your Admin Dashboard (recommended), or email backupwordpress@hmn.md', 'backupwordpress' ) . '</p>' .
51
 
52
- '<p><strong>' . __( 'How to get BackUpWordPress working in Heart Internet', 'backupwordpress' ) . '</strong></p>' .
53
 
54
- '<p>' . __( 'The script to be entered into the Heart Internet cPanel is: <code>/usr/bin/php5 /home/sites/yourdomain.com/public_html/wp-cron.php</code> (note the space between php5 and the location of the file). The file <code>wp-cron.php</code> <code>chmod</code> must be set to <code>711</code>.', 'backupwordpress' ) . '</p>' .
55
 
56
- '<p><strong>' . __( 'My backups seem to be failing?', 'backupwordpress' ) . '</strong></p>' .
57
 
58
- '<p>' . __( 'If your backups are failing, it\'s commonly caused by a lack of available resources on your server. To establish this is the case, exclude the complete (or parts of the) uploads folder and run a backup. If that succeeds, you know it\'s probably a server issue. If it does not succeed, report the results to our support team for further help. You can contact support by enabling support from your Admin Dashboard (recommended), or emailing backupwordpress@hmn.md', 'backupwordpress' ) . '</p>';
1
  <?php
2
  echo '<p><strong>' . __( 'Where does BackUpWordPress store the backup files?', 'backupwordpress' ) . '</strong></p>' .
3
 
4
+ '<p>' . __( 'Backups are stored on your server in <code>/wp-content/backups</code>, you can change the directory.', 'backupwordpress' ). '</p>' .
5
 
6
+ '<p>' . __( 'Important: By default BackUpWordPress backs up everything in your site root as well as your database, this includes any non WordPress folders that happen to be in your site root. This does mean that your backup directory can get quite large.', 'backupwordpress' ) . '</p>' .
7
 
8
+ '<p><strong>' . __( 'What if I want to back up my site to another destination?', 'backupwordpress' ) . '</strong></p>' .
9
 
10
+ '<p>' . __( 'BackUpWordPress Pro supports Dropbox, Google Drive, Amazon S3, Rackspace, Azure, DreamObjects and FTP/SFTP. Check it out here: <a href="http://bwp.hmn.md/?utm_source=wordpress-org&utm_medium=plugin-page&utm_campaign=freeplugin" title="BackUpWordPress Homepage" target="_blank">https://bwp.hmn.md</a>', 'backupwordpress' ) . '</p>' .
11
 
12
+ '<p><strong>' . __( 'How do I restore my site from a backup?', 'backupwordpress' ) . '</strong></p>' .
13
 
14
+ '<p>' . __( 'You need to download the latest backup file either by clicking download on the backups page or via <code>FTP</code>. <code>Unzip</code> the files and upload all the files to your server overwriting your site. You can then import the database using your hosts database management tool (likely <code>phpMyAdmin</code>).', 'backupwordpress' ) . '</p>' .
15
 
16
+ '<p>' . __( 'See this guide for more details - <a href="https://bwp.hmn.md/support-center/restore-backup/" title="Go to support center" target="_blank">How to restore from backup</a>.', 'backupwordpress' ) . '</p>' .
17
 
18
+ '<p><strong>' . __( 'Does BackUpWordPress back up the backups directory?', 'backupwordpress' ) . '</strong></p>' .
19
 
20
+ '<p>' . __( 'No.', 'backupwordpress' ) . '</p>' .
21
 
22
+ '<p><strong>' . __( 'I\'m not receiving my backups by email', 'backupwordpress' ) . '</strong></p>' .
23
 
24
+ '<p>' . __( 'Most servers have a filesize limit on email attachments, it\'s generally about 10mb. If your backup file is over that limit, it won\'t be sent attached to the email. Instead, you should receive an email with a link to download the backup. If you aren\'t even receiving that, then you likely have a mail issue on your server that you\'ll need to contact your host about.', 'backupwordpress' ) . '</p>' .
25
 
26
+ '<p><strong>' . __( 'How many backups are stored by default?', 'backupwordpress' ) . '</strong></p>' .
27
 
28
+ '<p>' . __( 'BackUpWordPress stores the last 10 backups by default.', 'backupwordpress' ) . '</p>' .
29
 
30
+ '<p><strong>' . __( 'How long should a backup take?', 'backupwordpress' ) . '</strong></p>' .
31
 
32
+ '<p>' . __( 'Unless your site is very large (many gigabytes) it should only take a few minutes to perform a backup. If your back up has been running for longer than an hour, it\'s safe to assume that something has gone wrong. Try de-activating and re-activating the plugin. If it keeps happening, contact support.', 'backupwordpress' ) . '</p>' .
33
 
34
+ '<p><strong>' . __( 'What do I do if I get the wp-cron error message?', 'backupwordpress' ) . '</strong></p>' .
35
 
36
+ '<p>' . __( 'The issue is that your <code>wp-cron.php</code> is not returning a <code>200</code> response when hit with a HTTP request originating from your own server, it could be several things. In most cases, it\'s an issue with the server / site.', 'backupwordpress' ) . '</p>' .
37
 
38
+ '<p>' . __( 'There are some things you can test to confirm this is the issue.', 'backupwordpress' ) . '</p>' .
39
 
40
+ '<ul><li>' . __( 'Are scheduled posts working? (They use wp-cron as well.)', 'backupwordpress' ) . '</li>' .
41
 
42
+ '<li>' . __( 'Are you hosted on Heart Internet? (wp-cron may not be supported by Heart Internet, see below for work-around.)', 'backupwordpress' ) . '</li>' .
43
 
44
+ '<li>' . __( 'If you click manual backup, does it work?', 'backupwordpress' ) . '</li>' .
45
 
46
+ '<li>' . __( 'Try adding <code>define( \'ALTERNATE_WP_CRON\', true );</code> to your <code>wp-config.php</code>. Do automatic backups work?', 'backupwordpress' ) . '</li>' .
47
 
48
+ '<li>' . __( 'Is your site private (i.e. is it behind some kind of authentication, maintenance plugin, .htaccess)? If so, wp-cron won\'t work until you remove it. If you are and you temporarily remove the authentication, do backups start working?', 'backupwordpress' ) . '</li></ul>' .
49
 
50
+ '<p>' . __( 'Report the results to our support team for further help. To do this, either enable support from your Admin Dashboard (recommended), or email backupwordpress@hmn.md', 'backupwordpress' ) . '</p>' .
51
 
52
+ '<p><strong>' . __( 'How to get BackUpWordPress working in Heart Internet', 'backupwordpress' ) . '</strong></p>' .
53
 
54
+ '<p>' . __( 'The script to be entered into the Heart Internet cPanel is: <code>/usr/bin/php5 /home/sites/yourdomain.com/public_html/wp-cron.php</code> (note the space between php5 and the location of the file). The file <code>wp-cron.php</code> <code>chmod</code> must be set to <code>711</code>.', 'backupwordpress' ) . '</p>' .
55
 
56
+ '<p><strong>' . __( 'My backups seem to be failing?', 'backupwordpress' ) . '</strong></p>' .
57
 
58
+ '<p>' . __( 'If your backups are failing, it\'s commonly caused by a lack of available resources on your server. To establish this is the case, exclude the complete (or parts of the) uploads folder and run a backup. If that succeeds, you know it\'s probably a server issue. If it does not succeed, report the results to our support team for further help. You can contact support by enabling support from your Admin Dashboard (recommended), or emailing backupwordpress@hmn.md', 'backupwordpress' ) . '</p>';
admin/menu.php CHANGED
@@ -5,18 +5,18 @@ namespace HM\BackUpWordPress;
5
  /**
6
  * Add the backups menu item
7
  * to the tools menu
8
- *
9
- * @return null
10
  */
11
  function admin_menu() {
12
 
13
  if ( is_multisite() ) {
14
- add_submenu_page( 'settings.php', __( 'Manage Backups', 'backupwordpress' ), __( 'Backups', 'backupwordpress' ), ( defined( 'HMBKP_CAPABILITY' ) && HMBKP_CAPABILITY ) ? HMBKP_CAPABILITY : 'manage_options', HMBKP_PLUGIN_SLUG, 'HM\BackUpWordPress\manage_backups' );
15
  } else {
16
  add_management_page( __( 'Manage Backups', 'backupwordpress' ), __( 'Backups', 'backupwordpress' ), ( defined( 'HMBKP_CAPABILITY' ) && HMBKP_CAPABILITY ) ? HMBKP_CAPABILITY : 'manage_options', HMBKP_PLUGIN_SLUG, 'HM\BackUpWordPress\manage_backups' );
17
  }
18
- }
19
 
 
 
 
20
  add_action( 'network_admin_menu', 'HM\BackUpWordPress\admin_menu' );
21
  add_action( 'admin_menu', 'HM\BackUpWordPress\admin_menu' );
22
 
@@ -30,6 +30,17 @@ function manage_backups() {
30
  require_once( HMBKP_PLUGIN_PATH . 'admin/page.php' );
31
  }
32
 
 
 
 
 
 
 
 
 
 
 
 
33
  /**
34
  * Add a link to the backups page to the plugin action links.
35
  *
@@ -47,7 +58,6 @@ function plugin_action_link( $links, $file ) {
47
  return $links;
48
 
49
  }
50
-
51
  add_filter( 'plugin_action_links', 'HM\BackUpWordPress\plugin_action_link', 10, 2 );
52
 
53
  /**
@@ -72,14 +82,16 @@ function contextual_help() {
72
  include_once( HMBKP_PLUGIN_PATH . 'admin/faq.php' );
73
  $faq = ob_get_clean();
74
 
75
- get_current_screen()->add_help_tab( array( 'title' => __( 'FAQ', 'backupwordpress' ),
76
- 'id' => 'hmbkp_faq',
77
- 'content' => wp_kses_post( $faq )
 
78
  ) );
79
 
80
- get_current_screen()->add_help_tab( array( 'title' => __( 'Constants', 'backupwordpress' ),
81
- 'id' => 'hmbkp_constants',
82
- 'content' => wp_kses_post( $constants )
 
83
  ) );
84
 
85
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-requirements.php' );
@@ -101,5 +113,4 @@ function contextual_help() {
101
  );
102
 
103
  }
104
-
105
  add_action( 'load-' . HMBKP_ADMIN_PAGE, 'HM\BackUpWordPress\contextual_help' );
5
  /**
6
  * Add the backups menu item
7
  * to the tools menu
 
 
8
  */
9
  function admin_menu() {
10
 
11
  if ( is_multisite() ) {
12
+ add_submenu_page( 'settings.php', __( 'Manage Backups | BackUpWordPress', 'backupwordpress' ), __( 'Backups', 'backupwordpress' ), ( defined( 'HMBKP_CAPABILITY' ) && HMBKP_CAPABILITY ) ? HMBKP_CAPABILITY : 'manage_options', HMBKP_PLUGIN_SLUG, 'HM\BackUpWordPress\manage_backups' );
13
  } else {
14
  add_management_page( __( 'Manage Backups', 'backupwordpress' ), __( 'Backups', 'backupwordpress' ), ( defined( 'HMBKP_CAPABILITY' ) && HMBKP_CAPABILITY ) ? HMBKP_CAPABILITY : 'manage_options', HMBKP_PLUGIN_SLUG, 'HM\BackUpWordPress\manage_backups' );
15
  }
 
16
 
17
+ add_submenu_page( null, __( 'BackUpWordPress Extensions', 'backupwordpress' ), __( 'Extensions', 'backupwordpress' ), ( defined( 'HMBKP_CAPABILITY' ) && HMBKP_CAPABILITY ) ? HMBKP_CAPABILITY : 'manage_options', HMBKP_PLUGIN_SLUG . '_extensions', 'HM\BackUpWordPress\extensions' );
18
+
19
+ }
20
  add_action( 'network_admin_menu', 'HM\BackUpWordPress\admin_menu' );
21
  add_action( 'admin_menu', 'HM\BackUpWordPress\admin_menu' );
22
 
30
  require_once( HMBKP_PLUGIN_PATH . 'admin/page.php' );
31
  }
32
 
33
+
34
+ /**
35
+ * Load the backups admin page
36
+ * when the menu option is clicked
37
+ *
38
+ * @return null
39
+ */
40
+ function extensions() {
41
+ require_once( HMBKP_PLUGIN_PATH . 'admin/extensions.php' );
42
+ }
43
+
44
  /**
45
  * Add a link to the backups page to the plugin action links.
46
  *
58
  return $links;
59
 
60
  }
 
61
  add_filter( 'plugin_action_links', 'HM\BackUpWordPress\plugin_action_link', 10, 2 );
62
 
63
  /**
82
  include_once( HMBKP_PLUGIN_PATH . 'admin/faq.php' );
83
  $faq = ob_get_clean();
84
 
85
+ get_current_screen()->add_help_tab( array(
86
+ 'title' => __( 'FAQ', 'backupwordpress' ),
87
+ 'id' => 'hmbkp_faq',
88
+ 'content' => wp_kses_post( $faq ),
89
  ) );
90
 
91
+ get_current_screen()->add_help_tab( array(
92
+ 'title' => __( 'Constants', 'backupwordpress' ),
93
+ 'id' => 'hmbkp_constants',
94
+ 'content' => wp_kses_post( $constants ),
95
  ) );
96
 
97
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-requirements.php' );
113
  );
114
 
115
  }
 
116
  add_action( 'load-' . HMBKP_ADMIN_PAGE, 'HM\BackUpWordPress\contextual_help' );
admin/page.php CHANGED
@@ -7,14 +7,18 @@ namespace HM\BackUpWordPress;
7
  <div class="wrap">
8
 
9
  <h1>
 
10
  BackUpWordPress
11
 
12
- <?php if ( get_option( 'hmbkp_enable_support' ) ) { ?>
 
 
 
13
  <a id="intercom" class="page-title-action" href="mailto:backupwordpress@hmn.md"><?php _e( 'Support', 'backupwordpress' ); ?></a>
14
- <?php } else {
15
  add_thickbox(); ?>
16
  <a id="intercom-info" class="thickbox page-title-action" href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'load_enable_support', 'width' => '600', 'height' => '420' ), self_admin_url( 'admin-ajax.php' ) ), 'hmbkp_nonce' ) ); ?>"><span class="dashicons dashicons-admin-users"></span>&nbsp;<?php _e( 'Enable Support', 'backupwordpress' ); ?></a>
17
- <?php } ?>
18
 
19
  </h1>
20
 
7
  <div class="wrap">
8
 
9
  <h1>
10
+
11
  BackUpWordPress
12
 
13
+ <a class="page-title-action" href="<?php echo esc_url( get_settings_url( HMBKP_PLUGIN_SLUG . '_extensions' ) ); ?>">Extensions</a>
14
+
15
+ <?php if ( get_option( 'hmbkp_enable_support' ) ) : ?>
16
+
17
  <a id="intercom" class="page-title-action" href="mailto:backupwordpress@hmn.md"><?php _e( 'Support', 'backupwordpress' ); ?></a>
18
+ <?php else :
19
  add_thickbox(); ?>
20
  <a id="intercom-info" class="thickbox page-title-action" href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'load_enable_support', 'width' => '600', 'height' => '420' ), self_admin_url( 'admin-ajax.php' ) ), 'hmbkp_nonce' ) ); ?>"><span class="dashicons dashicons-admin-users"></span>&nbsp;<?php _e( 'Enable Support', 'backupwordpress' ); ?></a>
21
+ <?php endif; ?>
22
 
23
  </h1>
24
 
admin/schedule-form-excludes.php CHANGED
@@ -25,15 +25,15 @@ $user_excludes = $excludes->get_user_excludes(); ?>
25
 
26
  <th scope="row">
27
 
28
- <?php if ( $exclude_path->isFile() ) { ?>
29
 
30
  <div class="dashicons dashicons-media-default"></div>
31
 
32
- <?php } elseif ( $exclude_path->isDir() ) { ?>
33
 
34
  <div class="dashicons dashicons-portfolio"></div>
35
 
36
- <?php } ?>
37
 
38
  </th>
39
 
@@ -81,15 +81,15 @@ $user_excludes = $excludes->get_user_excludes(); ?>
81
  // The directory to display
82
  $directory = Path::get_root();
83
 
84
- if ( isset( $_GET['hmbkp_directory_browse'] ) ) {
85
 
86
  $untrusted_directory = urldecode( $_GET['hmbkp_directory_browse'] );
87
 
88
  // Only allow real sub directories of the site root to be browsed
89
- if ( false !== strpos( $untrusted_directory, Path::get_root() ) && is_dir( $untrusted_directory ) ) {
90
  $directory = $untrusted_directory;
91
- }
92
- }
93
 
94
  $exclude_string = implode( '|', $excludes->get_excludes_for_regex() );
95
 
@@ -120,37 +120,37 @@ $user_excludes = $excludes->get_user_excludes(); ?>
120
 
121
  <th scope="col">
122
 
123
- <?php if ( Path::get_root() !== $directory ) { ?>
124
 
125
  <a href="<?php echo esc_url( remove_query_arg( 'hmbkp_directory_browse' ) ); ?>"><?php echo esc_html( Path::get_root() ); ?></a>
126
  <code>/</code>
127
 
128
  <?php $parents = array_filter( explode( '/', str_replace( trailingslashit( Path::get_root() ), '', trailingslashit( dirname( $directory ) ) ) ) );
129
 
130
- foreach ( $parents as $directory_basename ) { ?>
131
 
132
  <a href="<?php echo esc_url( add_query_arg( 'hmbkp_directory_browse', urlencode( substr( $directory, 0, strpos( $directory, $directory_basename ) ) . $directory_basename ) ) ); ?>"><?php echo esc_html( $directory_basename ); ?></a>
133
  <code>/</code>
134
 
135
- <?php } ?>
136
 
137
  <?php echo esc_html( basename( $directory ) ); ?>
138
 
139
- <?php } else { ?>
140
 
141
  <?php echo esc_html( Path::get_root() ); ?>
142
 
143
- <?php } ?>
144
 
145
  </th>
146
 
147
  <td class="column-filesize">
148
 
149
- <?php if ( Site_Size::is_site_size_being_calculated() ) { ?>
150
 
151
  <span class="spinner is-active"></span>
152
 
153
- <?php } else {
154
 
155
  $root = new \SplFileInfo( Path::get_root() );
156
 
@@ -163,7 +163,7 @@ $user_excludes = $excludes->get_user_excludes(); ?>
163
  <a class="dashicons dashicons-update" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'hmbkp_recalculate_directory_filesize', urlencode( Path::get_root() ) ), 'hmbkp-recalculate_directory_filesize' ) ); ?>"><span><?php _e( 'Refresh', 'backupwordpress' ); ?></span></a>
164
  </code>
165
 
166
- <?php } ?>
167
 
168
  <td>
169
  <code><?php echo esc_html( substr( sprintf( '%o', fileperms( Path::get_root() ) ), - 4 ) ); ?></code>
@@ -173,11 +173,11 @@ $user_excludes = $excludes->get_user_excludes(); ?>
173
 
174
  <code>
175
 
176
- <?php if ( is_link( Path::get_root() ) ) {
177
  _e( 'Symlink', 'backupwordpress' );
178
- } elseif ( is_dir( Path::get_root() ) ) {
179
  _e( 'Folder', 'backupwordpress' );
180
- } ?>
181
 
182
  </code>
183
 
@@ -191,168 +191,160 @@ $user_excludes = $excludes->get_user_excludes(); ?>
191
 
192
  <tbody>
193
 
194
- <?php if ( $files ) {
195
 
196
- foreach ( $files as $size => $file ) {
197
 
198
  $is_excluded = $is_unreadable = false;
199
 
200
  // Check if the file is excluded
201
- if ( $exclude_string && preg_match( '(' . $exclude_string . ')', str_ireplace( trailingslashit( Path::get_root() ), '', wp_normalize_path( $file->getPathname() ) ) ) ) {
202
  $is_excluded = true;
203
- }
204
 
205
  // Skip unreadable files
206
- if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) {
207
  $is_unreadable = true;
208
- } ?>
209
 
210
  <tr>
211
 
212
  <td>
213
 
214
- <?php if ( $is_unreadable ) { ?>
215
 
216
  <div class="dashicons dashicons-dismiss"></div>
217
 
218
- <?php } elseif ( $file->isFile() ) { ?>
219
 
220
  <div class="dashicons dashicons-media-default"></div>
221
 
222
- <?php } elseif ( $file->isDir() ) { ?>
223
 
224
  <div class="dashicons dashicons-portfolio"></div>
225
 
226
- <?php } ?>
227
 
228
  </td>
229
 
230
  <td>
231
 
232
- <?php if ( $is_unreadable ) { ?>
233
 
234
  <code class="strikethrough" title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>"><?php echo esc_html( $file->getBasename() ); ?></code>
235
 
236
- <?php } elseif ( $file->isFile() ) { ?>
237
 
238
  <code title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>"><?php echo esc_html( $file->getBasename() ); ?></code>
239
 
240
- <?php } elseif ( $file->isDir() ) { ?>
241
 
242
  <code title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>"><a href="<?php echo esc_url( add_query_arg( 'hmbkp_directory_browse', urlencode( wp_normalize_path( $file->getPathname() ) ) ) ); ?>"><?php echo esc_html( $file->getBasename() ); ?></a></code>
243
 
244
- <?php } ?>
245
 
246
  </td>
247
 
248
  <td class="column-format column-filesize">
249
 
250
- <?php if ( $file->isDir() && Site_Size::is_site_size_being_calculated() ) { ?>
251
-
252
  <span class="spinner is-active"></span>
253
-
254
- <?php } else {
255
-
256
  $size = $site_size->filesize( $file );
257
 
258
- if ( false !== $size ) {
259
-
260
  $size = size_format( $size ) ?: '0 B';
261
  $excluded_size = size_format( $excluded_site_size->filesize( $file ) ) ?: '0'; ?>
262
 
263
  <code>
264
 
265
- <?php if ( $file->isDir() ) {
266
  $excluded_size = is_same_size_format( $size, $excluded_size ) ? (int) size_format( $excluded_size ) : size_format( $excluded_size );
267
  echo sprintf( __( '%s of %s', 'backupwordpress' ), esc_html( $excluded_size ), esc_html( size_format( $size ) ) );
268
- } elseif ( ! $is_unreadable ) {
269
  echo esc_html( $size );
270
- } else {
271
  echo '-';
272
- } ?>
273
 
274
  </code>
275
 
276
- <?php } else { ?>
277
 
278
  <code>--</code>
279
 
280
- <?php }
281
- } ?>
282
 
283
  </td>
284
 
285
  <td>
286
  <code>
287
- <?php if ( ! $is_unreadable ) {
288
  echo esc_html( substr( sprintf( '%o', $file->getPerms() ), - 4 ) );
289
- } else {
290
  echo '-';
291
- } ?>
292
  </code>
293
  </td>
294
 
295
  <td>
296
  <code>
297
- <?php if ( $file->isLink() ) { ?>
298
-
299
  <span title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>"><?php _e( 'Symlink', 'backupwordpress' ); ?></span>
300
-
301
- <?php } elseif ( $file->isDir() ) {
302
  _e( 'Folder', 'backupwordpress' );
303
- } else {
304
  _e( 'File', 'backupwordpress' );
305
- } ?>
306
  </code>
307
  </td>
308
 
309
  <td class="column-format">
310
 
311
- <?php if ( $is_unreadable ) { ?>
312
 
313
  <strong title="<?php _e( 'Unreadable files won\'t be backed up.', 'backupwordpress' ); ?>"><?php _e( 'Unreadable', 'backupwordpress' ); ?></strong>
314
 
315
- <?php } elseif ( $is_excluded ) { ?>
316
 
317
  <strong><?php _e( 'Excluded', 'backupwordpress' ); ?></strong>
318
 
319
- <?php } else {
320
 
321
  $exclude_path = $file->getPathname();
322
 
323
  // Excluded directories need to be trailingslashed
324
- if ( $file->isDir() ) {
325
  $exclude_path = trailingslashit( wp_normalize_path( $file->getPathname() ) );
326
- } ?>
327
 
328
  <a href="<?php echo esc_url( wp_nonce_url( add_query_arg( array(
329
  'hmbkp_schedule_id' => $schedule->get_id(),
330
  'action' => 'hmbkp_add_exclude_rule',
331
  'hmbkp_exclude_pathname' => urlencode( $exclude_path ),
332
- ), admin_url( 'admin-post.php' ) ), 'hmbkp-add-exclude-rule', 'hmbkp-add-exclude-rule-nonce' ) ); ?>"
333
- class="button-secondary"><?php _e( 'Exclude &rarr;', 'backupwordpress' ); ?></a>
334
 
335
- <?php } ?>
336
 
337
  </td>
338
 
339
  </tr>
340
 
341
- <?php } ?>
342
 
343
- <?php } else { ?>
344
 
345
  <tr>
346
  <td colspan="5"><span class="description"><?php _e( 'This folder is empty', 'backupwordpress' ); ?></span></td>
347
  </tr>
348
 
349
- <?php } ?>
350
 
351
  </tbody>
352
 
353
  </table>
354
 
355
-
356
  <p class="submit">
357
  <a href="<?php echo esc_url( get_settings_url() ) ?>" class="button-primary"><?php _e( 'Done', 'backupwordpress' ); ?></a>
358
  </p>
25
 
26
  <th scope="row">
27
 
28
+ <?php if ( $exclude_path->isFile() ) : ?>
29
 
30
  <div class="dashicons dashicons-media-default"></div>
31
 
32
+ <?php elseif ( $exclude_path->isDir() ) : ?>
33
 
34
  <div class="dashicons dashicons-portfolio"></div>
35
 
36
+ <?php endif; ?>
37
 
38
  </th>
39
 
81
  // The directory to display
82
  $directory = Path::get_root();
83
 
84
+ if ( isset( $_GET['hmbkp_directory_browse'] ) ) :
85
 
86
  $untrusted_directory = urldecode( $_GET['hmbkp_directory_browse'] );
87
 
88
  // Only allow real sub directories of the site root to be browsed
89
+ if ( false !== strpos( $untrusted_directory, Path::get_root() ) && is_dir( $untrusted_directory ) ) :
90
  $directory = $untrusted_directory;
91
+ endif;
92
+ endif;
93
 
94
  $exclude_string = implode( '|', $excludes->get_excludes_for_regex() );
95
 
120
 
121
  <th scope="col">
122
 
123
+ <?php if ( Path::get_root() !== $directory ) : ?>
124
 
125
  <a href="<?php echo esc_url( remove_query_arg( 'hmbkp_directory_browse' ) ); ?>"><?php echo esc_html( Path::get_root() ); ?></a>
126
  <code>/</code>
127
 
128
  <?php $parents = array_filter( explode( '/', str_replace( trailingslashit( Path::get_root() ), '', trailingslashit( dirname( $directory ) ) ) ) );
129
 
130
+ foreach ( $parents as $directory_basename ) : ?>
131
 
132
  <a href="<?php echo esc_url( add_query_arg( 'hmbkp_directory_browse', urlencode( substr( $directory, 0, strpos( $directory, $directory_basename ) ) . $directory_basename ) ) ); ?>"><?php echo esc_html( $directory_basename ); ?></a>
133
  <code>/</code>
134
 
135
+ <?php endforeach; ?>
136
 
137
  <?php echo esc_html( basename( $directory ) ); ?>
138
 
139
+ <?php else : ?>
140
 
141
  <?php echo esc_html( Path::get_root() ); ?>
142
 
143
+ <?php endif; ?>
144
 
145
  </th>
146
 
147
  <td class="column-filesize">
148
 
149
+ <?php if ( Site_Size::is_site_size_being_calculated() ) : ?>
150
 
151
  <span class="spinner is-active"></span>
152
 
153
+ <?php else :
154
 
155
  $root = new \SplFileInfo( Path::get_root() );
156
 
163
  <a class="dashicons dashicons-update" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'hmbkp_recalculate_directory_filesize', urlencode( Path::get_root() ) ), 'hmbkp-recalculate_directory_filesize' ) ); ?>"><span><?php _e( 'Refresh', 'backupwordpress' ); ?></span></a>
164
  </code>
165
 
166
+ <?php endif; ?>
167
 
168
  <td>
169
  <code><?php echo esc_html( substr( sprintf( '%o', fileperms( Path::get_root() ) ), - 4 ) ); ?></code>
173
 
174
  <code>
175
 
176
+ <?php if ( is_link( Path::get_root() ) ) :
177
  _e( 'Symlink', 'backupwordpress' );
178
+ elseif ( is_dir( Path::get_root() ) ) :
179
  _e( 'Folder', 'backupwordpress' );
180
+ endif; ?>
181
 
182
  </code>
183
 
191
 
192
  <tbody>
193
 
194
+ <?php if ( $files ) :
195
 
196
+ foreach ( $files as $size => $file ) :
197
 
198
  $is_excluded = $is_unreadable = false;
199
 
200
  // Check if the file is excluded
201
+ if ( $exclude_string && preg_match( '(' . $exclude_string . ')', str_ireplace( trailingslashit( Path::get_root() ), '', wp_normalize_path( $file->getPathname() ) ) ) ) :
202
  $is_excluded = true;
203
+ endif;
204
 
205
  // Skip unreadable files
206
+ if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) :
207
  $is_unreadable = true;
208
+ endif; ?>
209
 
210
  <tr>
211
 
212
  <td>
213
 
214
+ <?php if ( $is_unreadable ) : ?>
215
 
216
  <div class="dashicons dashicons-dismiss"></div>
217
 
218
+ <?php elseif ( $file->isFile() ) : ?>
219
 
220
  <div class="dashicons dashicons-media-default"></div>
221
 
222
+ <?php elseif ( $file->isDir() ) : ?>
223
 
224
  <div class="dashicons dashicons-portfolio"></div>
225
 
226
+ <?php endif; ?>
227
 
228
  </td>
229
 
230
  <td>
231
 
232
+ <?php if ( $is_unreadable ) : ?>
233
 
234
  <code class="strikethrough" title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>"><?php echo esc_html( $file->getBasename() ); ?></code>
235
 
236
+ <?php elseif ( $file->isFile() ) : ?>
237
 
238
  <code title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>"><?php echo esc_html( $file->getBasename() ); ?></code>
239
 
240
+ <?php elseif ( $file->isDir() ) : ?>
241
 
242
  <code title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>"><a href="<?php echo esc_url( add_query_arg( 'hmbkp_directory_browse', urlencode( wp_normalize_path( $file->getPathname() ) ) ) ); ?>"><?php echo esc_html( $file->getBasename() ); ?></a></code>
243
 
244
+ <?php endif; ?>
245
 
246
  </td>
247
 
248
  <td class="column-format column-filesize">
249
 
250
+ <?php if ( $file->isDir() && Site_Size::is_site_size_being_calculated() ) : ?>
 
251
  <span class="spinner is-active"></span>
252
+ <?php else :
 
 
253
  $size = $site_size->filesize( $file );
254
 
255
+ if ( false !== $size ) :
 
256
  $size = size_format( $size ) ?: '0 B';
257
  $excluded_size = size_format( $excluded_site_size->filesize( $file ) ) ?: '0'; ?>
258
 
259
  <code>
260
 
261
+ <?php if ( $file->isDir() ) :
262
  $excluded_size = is_same_size_format( $size, $excluded_size ) ? (int) size_format( $excluded_size ) : size_format( $excluded_size );
263
  echo sprintf( __( '%s of %s', 'backupwordpress' ), esc_html( $excluded_size ), esc_html( size_format( $size ) ) );
264
+ elseif ( ! $is_unreadable ) :
265
  echo esc_html( $size );
266
+ else :
267
  echo '-';
268
+ endif; ?>
269
 
270
  </code>
271
 
272
+ <?php else : ?>
273
 
274
  <code>--</code>
275
 
276
+ <?php endif;
277
+ endif; ?>
278
 
279
  </td>
280
 
281
  <td>
282
  <code>
283
+ <?php if ( ! $is_unreadable ) :
284
  echo esc_html( substr( sprintf( '%o', $file->getPerms() ), - 4 ) );
285
+ else :
286
  echo '-';
287
+ endif; ?>
288
  </code>
289
  </td>
290
 
291
  <td>
292
  <code>
293
+ <?php if ( $file->isLink() ) : ?>
 
294
  <span title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>"><?php _e( 'Symlink', 'backupwordpress' ); ?></span>
295
+ <?php elseif ( $file->isDir() ) :
 
296
  _e( 'Folder', 'backupwordpress' );
297
+ else :
298
  _e( 'File', 'backupwordpress' );
299
+ endif; ?>
300
  </code>
301
  </td>
302
 
303
  <td class="column-format">
304
 
305
+ <?php if ( $is_unreadable ) : ?>
306
 
307
  <strong title="<?php _e( 'Unreadable files won\'t be backed up.', 'backupwordpress' ); ?>"><?php _e( 'Unreadable', 'backupwordpress' ); ?></strong>
308
 
309
+ <?php elseif ( $is_excluded ) : ?>
310
 
311
  <strong><?php _e( 'Excluded', 'backupwordpress' ); ?></strong>
312
 
313
+ <?php else :
314
 
315
  $exclude_path = $file->getPathname();
316
 
317
  // Excluded directories need to be trailingslashed
318
+ if ( $file->isDir() ) :
319
  $exclude_path = trailingslashit( wp_normalize_path( $file->getPathname() ) );
320
+ endif; ?>
321
 
322
  <a href="<?php echo esc_url( wp_nonce_url( add_query_arg( array(
323
  'hmbkp_schedule_id' => $schedule->get_id(),
324
  'action' => 'hmbkp_add_exclude_rule',
325
  'hmbkp_exclude_pathname' => urlencode( $exclude_path ),
326
+ ), admin_url( 'admin-post.php' ) ), 'hmbkp-add-exclude-rule', 'hmbkp-add-exclude-rule-nonce' ) ); ?>" class="button-secondary"><?php _e( 'Exclude &rarr;', 'backupwordpress' ); ?></a>
 
327
 
328
+ <?php endif; ?>
329
 
330
  </td>
331
 
332
  </tr>
333
 
334
+ <?php endforeach; ?>
335
 
336
+ <?php else : ?>
337
 
338
  <tr>
339
  <td colspan="5"><span class="description"><?php _e( 'This folder is empty', 'backupwordpress' ); ?></span></td>
340
  </tr>
341
 
342
+ <?php endif; ?>
343
 
344
  </tbody>
345
 
346
  </table>
347
 
 
348
  <p class="submit">
349
  <a href="<?php echo esc_url( get_settings_url() ) ?>" class="button-primary"><?php _e( 'Done', 'backupwordpress' ); ?></a>
350
  </p>
admin/schedule-form.php CHANGED
@@ -13,7 +13,7 @@ namespace HM\BackUpWordPress;
13
  <div id="hmbkp-warning" class="error settings-error">
14
 
15
  <?php foreach ( $hmbkp_form_errors as $error ) { ?>
16
- <p><strong><?php echo esc_html( $error ); ?></strong></p>
17
  <?php } ?>
18
 
19
  </div>
@@ -86,9 +86,9 @@ clear_settings_errors();
86
 
87
  </tr>
88
 
89
- <?php if ( ! $start_time = $schedule->get_schedule_start_time( false ) ) {
90
  $start_time = time();
91
- } ?>
92
 
93
  <?php $start_date_array = date_parse( date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $start_time ) ); ?>
94
 
@@ -109,7 +109,7 @@ clear_settings_errors();
109
  'thursday' => __( 'Thursday', 'backupwordpress' ),
110
  'friday' => __( 'Friday', 'backupwordpress' ),
111
  'saturday' => __( 'Saturday', 'backupwordpress' ),
112
- 'sunday' => __( 'Sunday', 'backupwordpress' )
113
  );
114
 
115
  foreach ( $weekdays as $key => $day ) : ?>
@@ -183,9 +183,9 @@ clear_settings_errors();
183
 
184
  $site_size = new Site_Size;
185
 
186
- if ( $site_size->is_site_size_cached() ) {
187
  printf( __( 'This schedule will store a maximum of %s of backups.', 'backupwordpress' ), '<code>' . esc_html( size_format( $site_size->get_site_size( $schedule->get_type(), $schedule->get_excludes() ) * $schedule->get_max_backups() ) ) . '</code>' );
188
- } ?>
189
 
190
  </p>
191
 
@@ -193,9 +193,9 @@ clear_settings_errors();
193
 
194
  </tr>
195
 
196
- <?php foreach ( Services::get_services( $schedule ) as $service ) {
197
  $service->field();
198
- } ?>
199
 
200
  </tbody>
201
 
13
  <div id="hmbkp-warning" class="error settings-error">
14
 
15
  <?php foreach ( $hmbkp_form_errors as $error ) { ?>
16
+ <p><strong><?php echo wp_kses_data( $error ); ?></strong></p>
17
  <?php } ?>
18
 
19
  </div>
86
 
87
  </tr>
88
 
89
+ <?php if ( ! $start_time = $schedule->get_schedule_start_time( false ) ) :
90
  $start_time = time();
91
+ endif; ?>
92
 
93
  <?php $start_date_array = date_parse( date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $start_time ) ); ?>
94
 
109
  'thursday' => __( 'Thursday', 'backupwordpress' ),
110
  'friday' => __( 'Friday', 'backupwordpress' ),
111
  'saturday' => __( 'Saturday', 'backupwordpress' ),
112
+ 'sunday' => __( 'Sunday', 'backupwordpress' ),
113
  );
114
 
115
  foreach ( $weekdays as $key => $day ) : ?>
183
 
184
  $site_size = new Site_Size;
185
 
186
+ if ( $site_size->is_site_size_cached() ) :
187
  printf( __( 'This schedule will store a maximum of %s of backups.', 'backupwordpress' ), '<code>' . esc_html( size_format( $site_size->get_site_size( $schedule->get_type(), $schedule->get_excludes() ) * $schedule->get_max_backups() ) ) . '</code>' );
188
+ endif; ?>
189
 
190
  </p>
191
 
193
 
194
  </tr>
195
 
196
+ <?php foreach ( Services::get_services( $schedule ) as $service ) :
197
  $service->field();
198
+ endforeach; ?>
199
 
200
  </tbody>
201
 
admin/schedule-sentence.php CHANGED
@@ -104,20 +104,16 @@ foreach ( Services::get_services( $schedule ) as $file => $service ) {
104
 
105
  if ( is_wp_error( $service ) ) {
106
  $email_msg = $service->get_error_message();
107
- } elseif ( 'Email' === $service->name ) {
108
  $email_msg = wp_kses_post( $service->display() );
109
  } elseif ( $service->is_service_active() && $service->display() ) {
110
  $services[] = esc_html( $service->display() );
111
  }
112
-
113
  }
114
 
115
  if ( ! empty( $services ) && count( $services ) > 1 ) {
116
-
117
- $services[count( $services ) -2] .= ' & ' . $services[count( $services ) -1];
118
-
119
  array_pop( $services );
120
-
121
  } ?>
122
 
123
  <div class="hmbkp-schedule-sentence<?php if ( $status->get_status() ) { ?> hmbkp-running<?php } ?>">
@@ -134,9 +130,9 @@ if ( ! empty( $services ) && count( $services ) > 1 ) {
134
 
135
  echo $sentence; ?>
136
 
137
- <?php if ( Schedules::get_instance()->get_schedule( $schedule->get_id() ) ) {
138
  schedule_status( $schedule );
139
- } ?>
140
 
141
  <?php require( HMBKP_PLUGIN_PATH . 'admin/schedule-settings.php' ); ?>
142
 
@@ -161,13 +157,9 @@ function get_site_size_text( Scheduled_Backup $schedule ) {
161
  $site_size = new Site_Size( $schedule->get_type(), $schedule->get_excludes() );
162
 
163
  if ( ( 'database' === $schedule->get_type() ) || $site_size->is_site_size_cached() ) {
164
-
165
  return sprintf( '(<code title="' . __( 'Backups will be compressed and should be smaller than this.', 'backupwordpress' ) . '">%s</code>)', esc_attr( $site_size->get_formatted_site_size() ) );
166
-
167
  } else {
168
-
169
  return sprintf( '(<code class="calculating" title="' . __( 'this shouldn\'t take long&hellip;', 'backupwordpress' ) . '">' . __( 'calculating the size of your site&hellip;', 'backupwordpress' ) . '</code>)' );
170
-
171
  }
172
 
173
  }
104
 
105
  if ( is_wp_error( $service ) ) {
106
  $email_msg = $service->get_error_message();
107
+ } elseif ( 'Email' === $service->name ) {
108
  $email_msg = wp_kses_post( $service->display() );
109
  } elseif ( $service->is_service_active() && $service->display() ) {
110
  $services[] = esc_html( $service->display() );
111
  }
 
112
  }
113
 
114
  if ( ! empty( $services ) && count( $services ) > 1 ) {
115
+ $services[ count( $services ) -2 ] .= ' & ' . $services[ count( $services ) -1 ];
 
 
116
  array_pop( $services );
 
117
  } ?>
118
 
119
  <div class="hmbkp-schedule-sentence<?php if ( $status->get_status() ) { ?> hmbkp-running<?php } ?>">
130
 
131
  echo $sentence; ?>
132
 
133
+ <?php if ( Schedules::get_instance()->get_schedule( $schedule->get_id() ) ) :
134
  schedule_status( $schedule );
135
+ endif; ?>
136
 
137
  <?php require( HMBKP_PLUGIN_PATH . 'admin/schedule-settings.php' ); ?>
138
 
157
  $site_size = new Site_Size( $schedule->get_type(), $schedule->get_excludes() );
158
 
159
  if ( ( 'database' === $schedule->get_type() ) || $site_size->is_site_size_cached() ) {
 
160
  return sprintf( '(<code title="' . __( 'Backups will be compressed and should be smaller than this.', 'backupwordpress' ) . '">%s</code>)', esc_attr( $site_size->get_formatted_site_size() ) );
 
161
  } else {
 
162
  return sprintf( '(<code class="calculating" title="' . __( 'this shouldn\'t take long&hellip;', 'backupwordpress' ) . '">' . __( 'calculating the size of your site&hellip;', 'backupwordpress' ) . '</code>)' );
 
163
  }
164
 
165
  }
admin/schedule-settings.php CHANGED
@@ -19,10 +19,11 @@ if ( Schedules::get_instance()->get_schedule( $schedule->get_id() ) ) { ?>
19
 
20
  <?php foreach ( Services::get_services( $schedule ) as $service ) :
21
 
22
- if ( ! $service->has_form() )
23
- continue; ?>
 
24
 
25
- <a href="<?php echo esc_url( add_query_arg( array( 'action' => 'hmbkp_edit_schedule', 'hmbkp_panel' => 'hmbkp_edit_schedule_settings_' . $service->get_slug() , 'hmbkp_schedule_id' => $schedule->get_id() ), get_settings_url() ) ); ?>"><?php echo esc_html( $service->name ); ?></a> |
26
 
27
  <?php endforeach; ?>
28
 
@@ -38,24 +39,22 @@ if ( Schedules::get_instance()->get_schedule( $schedule->get_id() ) ) { ?>
38
 
39
  <div class="hmbkp-schedule-settings">
40
 
41
- <?php if ( $_GET['action'] === 'hmbkp_edit_schedule' && $_GET['hmbkp_panel'] === 'hmbkp_edit_schedule_settings' ) {
42
  require( HMBKP_PLUGIN_PATH . 'admin/schedule-form.php' );
43
- } ?>
44
 
45
- <?php if ( $_GET['action'] === 'hmbkp_edit_schedule' && $_GET['hmbkp_panel'] === 'hmbkp_edit_schedule_excludes' ) {
46
  require( HMBKP_PLUGIN_PATH . 'admin/schedule-form-excludes.php' );
47
- } ?>
48
 
49
  <?php // Show the service form if we are viewing one
50
  foreach ( Services::get_services( $schedule ) as $service ) : ?>
51
 
52
- <?php if ( $_GET['action'] === 'hmbkp_edit_schedule' && $_GET['hmbkp_panel'] === 'hmbkp_edit_schedule_settings_' . $service->get_slug() ) { ?>
53
 
54
  <h3><?php echo esc_html( $service->name ); ?></h3>
55
 
56
- <?php
57
-
58
- $hmbkp_form_errors = get_settings_errors();
59
 
60
  if ( ! empty( $hmbkp_form_errors ) ) :
61
 
@@ -63,20 +62,16 @@ if ( Schedules::get_instance()->get_schedule( $schedule->get_id() ) ) { ?>
63
 
64
  <div id="hmbkp-warning" class="error settings-error">
65
 
66
- <?php foreach ( $hmbkp_form_errors as $error ) { ?>
67
  <p><strong><?php echo esc_html( $error ); ?></strong></p>
68
- <?php } ?>
69
 
70
  </div>
71
 
72
- <?php
73
-
74
- endif;
75
 
76
  // We can clear them now we've displayed them
77
- clear_settings_errors();
78
-
79
- ?>
80
 
81
  <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
82
 
@@ -93,8 +88,8 @@ if ( Schedules::get_instance()->get_schedule( $schedule->get_id() ) ) { ?>
93
 
94
  <?php break; ?>
95
 
96
- <?php } ?>
97
 
98
  <?php endforeach; ?>
99
 
100
- </div>
19
 
20
  <?php foreach ( Services::get_services( $schedule ) as $service ) :
21
 
22
+ if ( ! $service->has_form() ) {
23
+ continue;
24
+ } ?>
25
 
26
+ <a href="<?php echo esc_url( add_query_arg( array( 'action' => 'hmbkp_edit_schedule', 'hmbkp_panel' => 'hmbkp_edit_schedule_settings_' . $service->get_slug(), 'hmbkp_schedule_id' => $schedule->get_id() ), get_settings_url() ) ); ?>"><?php echo esc_html( $service->name ); ?></a> |
27
 
28
  <?php endforeach; ?>
29
 
39
 
40
  <div class="hmbkp-schedule-settings">
41
 
42
+ <?php if ( 'hmbkp_edit_schedule' === $_GET['action'] && 'hmbkp_edit_schedule_settings' === $_GET['hmbkp_panel'] ) :
43
  require( HMBKP_PLUGIN_PATH . 'admin/schedule-form.php' );
44
+ endif; ?>
45
 
46
+ <?php if ( 'hmbkp_edit_schedule' === $_GET['action'] && 'hmbkp_edit_schedule_excludes' === $_GET['hmbkp_panel'] ) :
47
  require( HMBKP_PLUGIN_PATH . 'admin/schedule-form-excludes.php' );
48
+ endif; ?>
49
 
50
  <?php // Show the service form if we are viewing one
51
  foreach ( Services::get_services( $schedule ) as $service ) : ?>
52
 
53
+ <?php if ( 'hmbkp_edit_schedule' === $_GET['action'] && 'hmbkp_edit_schedule_settings_' . $service->get_slug() === $_GET['hmbkp_panel'] ) : ?>
54
 
55
  <h3><?php echo esc_html( $service->name ); ?></h3>
56
 
57
+ <?php $hmbkp_form_errors = get_settings_errors();
 
 
58
 
59
  if ( ! empty( $hmbkp_form_errors ) ) :
60
 
62
 
63
  <div id="hmbkp-warning" class="error settings-error">
64
 
65
+ <?php foreach ( $hmbkp_form_errors as $error ) : ?>
66
  <p><strong><?php echo esc_html( $error ); ?></strong></p>
67
+ <?php endforeach; ?>
68
 
69
  </div>
70
 
71
+ <?php endif;
 
 
72
 
73
  // We can clear them now we've displayed them
74
+ clear_settings_errors(); ?>
 
 
75
 
76
  <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
77
 
88
 
89
  <?php break; ?>
90
 
91
+ <?php endif; ?>
92
 
93
  <?php endforeach; ?>
94
 
95
+ </div>
admin/server-info.php CHANGED
@@ -58,6 +58,6 @@ foreach ( HM\BackUpWordPress\Requirements::get_requirement_groups() as $group )
58
 
59
  <?php endforeach;
60
 
61
- foreach ( HM\BackUpWordPress\Services::get_services() as $file => $service ) {
62
  echo wp_kses_post( call_user_func( array( $service, 'intercom_data_html' ) ) );
63
- }
58
 
59
  <?php endforeach;
60
 
61
+ foreach ( HM\BackUpWordPress\Services::get_services() as $file => $service ) :
62
  echo wp_kses_post( call_user_func( array( $service, 'intercom_data_html' ) ) );
63
+ endforeach;
admin/upsell.php CHANGED
@@ -1,26 +1,17 @@
 
1
  <div class="hmbkp-upsell">
2
 
3
- <span><?php esc_html_e( 'Backup to', 'backupwordpress' ); ?></span>&nbsp;
4
-
5
- <span class="hmbkp-upsell-sep">
6
- <a target="_blank" href="http://bwp.hmn.md/downloads/backupwordpress-to-dropbox/">Dropbox</a> |
7
- <a target="_blank" href="http://bwp.hmn.md/downloads/backupwordpress-to-google-drive/">Google Drive</a> |
8
- <a target="_blank" href="http://bwp.hmn.md/downloads/backupwordpress-to-amazon-s3/">Amazon S3</a> |
9
- <a target="_blank" href="http://bwp.hmn.md/downloads/backupwordpress-to-ftp/">FTP</a> |
10
- <a target="_blank" href="http://bwp.hmn.md/downloads/backupwordpress-to-rackspace-cloud/">Rackspace Cloud</a> |
11
- <a target="_blank" href="http://bwp.hmn.md/downloads/backupwordpress-to-windows-azure/">Windows Azure</a> |
12
- <a target="_blank" href="http://bwp.hmn.md/downloads/backupwordpress-to-dreamobjects/">DreamObjects</a>
13
- </span>&nbsp;
14
 
15
  <?php
16
-
17
  printf(
18
- __( '%1$sor buy the %2$sDeveloper Bundle%3$s now for only &dollar;99 (all Destinations &amp; Unlimited Sites)%4$s', 'backupwordpress' ),
19
- '<span>',
20
- '<a target="_blank" href="https://bwp.hmn.md/checkout?edd_action=add_to_cart&download_id=36">',
21
- '</a>',
22
- '</span>'
23
  );
24
-
25
  ?>
26
- </div>
 
 
 
1
+ <?php namespace HM\BackUpWordPress; ?>
2
  <div class="hmbkp-upsell">
3
 
4
+ <p>
 
 
 
 
 
 
 
 
 
 
5
 
6
  <?php
7
+ /** translators: the 1st placeholder is the first part of the anchor tag with the link to the extensions admin page and the second is the closing anchor tag */
8
  printf(
9
+ __( 'Store your backups securely in the Cloud with %1$sour extensions%2$s', 'backupwordpress' ),
10
+ '<a href="' . esc_url( get_settings_url( HMBKP_PLUGIN_SLUG . '_extensions' ) ) . '">',
11
+ '</a>'
 
 
12
  );
 
13
  ?>
14
+
15
+ </p>
16
+
17
+ </div>
assets/hmbkp.css CHANGED
@@ -95,3 +95,8 @@ pre { background-color: #eee; padding: 10px; white-space: pre; max-height: 320px
95
  table.widefat tbody tr:nth-child(odd) { background-color: #f9f9f9 }
96
 
97
  }
 
 
 
 
 
95
  table.widefat tbody tr:nth-child(odd) { background-color: #f9f9f9 }
96
 
97
  }
98
+
99
+ .tools_page_backupwordpress_extensions a[href*="page=backupwordpress"] {
100
+ font-weight: bold !important;
101
+ color: white !important;
102
+ }
assets/hmbkp.js CHANGED
@@ -19,6 +19,15 @@ var BackUpWordPressAdmin = (function($){
19
 
20
  }
21
 
 
 
 
 
 
 
 
 
 
22
  // Show delete confirm message for delete schedule
23
  $( document ).on( 'click', '.hmbkp-schedule-actions .delete-action', function ( e ) {
24
 
@@ -121,7 +130,7 @@ var BackUpWordPressAdmin = (function($){
121
 
122
  } );
123
 
124
- $( document ).on( 'click', '#hmbkp-warning-backup .notice-dismiss', function(){
125
  $.post(
126
  ajaxurl,
127
  {
19
 
20
  }
21
 
22
+ $('.notice.is-dismissible').on('click', '.notice-dismiss', function(){
23
+ $.post(
24
+ ajaxurl,
25
+ {
26
+ 'action': 'hmbkp_dismiss_notice'
27
+ }
28
+ );
29
+ });
30
+
31
  // Show delete confirm message for delete schedule
32
  $( document ).on( 'click', '.hmbkp-schedule-actions .delete-action', function ( e ) {
33
 
130
 
131
  } );
132
 
133
+ $( document ).on( 'click', '[id^="hmbkp-warning-"] .notice-dismiss', function(){
134
  $.post(
135
  ajaxurl,
136
  {
assets/hmbkp.min.css CHANGED
@@ -1 +1 @@
1
- .hmbkp-schedule-actions a,.hmbkp-schedule-settings .column-format code{white-space:nowrap}.hmbkp_active td:first-child>code:before{content:"\00a0 \2713 ";font-size:11px}.hmbkp_active{background:#E5F7E8}div#hmbkp-warning,h2.nav-tab-wrapper+div[id^=hmbkp]{margin:20px 0 15px}h2+div[id^=hmbkp] input{max-width:100%}li a.hmbkp-running:not(.current):before{width:20px;height:20px;margin:-1px 10px -5px 0;content:"";background:url(spinner-2x.gif) no-repeat;background-size:20px;display:inline-block}.hmbkp-upsell{margin-top:40px;padding-top:16px;border-top:1px solid #ccc}.hmbkp-upsell a{color:#57792b}.hmbkp-upsell a:hover{color:#98c063}.hmbkp-upsell-sep{color:#bbb}.hmbkp-upsell ul{overflow:hidden}.hmbkp-upsell li{float:left;margin:0 20px 20px 0}.hmbkp-upsell img{display:block;margin:0 auto;max-width:120px;min-height:60px}.hmbkp-upsell ul a{display:block;margin-bottom:0;width:120px}.hmbkp-upsell .howto{font-weight:400;display:inline}.hmbkp-upsell .hmbkp_hide{float:right}.hmbkp-schedule-sentence{font-size:16px;font-weight:lighter;margin:0 0 20px;background-color:#FBFBFB;padding:20px;border:1px solid #e5e5e5;box-shadow:0 1px 1px rgba(0,0,0,.04)}.hmbkp-schedule-sentence::before{content:"\2714";margin-right:10px;width:16px;height:60px;display:block;float:left}.hmbkp-schedule-sentence.hmbkp-error:before{content:"\2718"}.hmbkp-schedule-sentence.hmbkp-running:before{width:20px;height:80px;margin:-1px 10px 0 0;content:"";background:url(spinner-2x.gif) no-repeat;background-size:20px;display:inline-block}.hmbkp-schedule-sentence .hmbkp-status{display:none;font-size:12px;color:#666;margin:2px 0 0 30px}.hmbkp-schedule-sentence.hmbkp-running .hmbkp-status{display:block}.hmbkp-schedule-sentence.hmbkp-running .hmbkp-schedule-actions{display:none}.hmbkp-schedule-sentence :not(a)[title]{border-bottom:1px dotted #CCC;cursor:help}.hmbkp-schedule-sentence .hmbkp-status[title]{border-bottom:none}.hmbkp-schedule-sentence .submit{padding:0}.hmbkp-schedule-sentence .hmbkp-schedule-actions{visibility:visible;font-size:12px;font-weight:400;margin:0 0 0 26px}.hmbkp-schedule-sentence .row-actions{position:static}.hmbkp-schedule-settings{border-top:1px solid #e5e5e5;margin:20px -20px -20px;background-color:#f5f5f5;padding:0 20px 20px}.hmbkp-exclude-settings thead tr:last-child,table.widefat tbody tr:nth-child(odd){background-color:#f9f9f9}.hmbkp-ajax-loading,button.hmbkp-ajax-loading{padding-left:20px;position:relative}.hmbkp-ajax-loading::after{content:"";width:16px;height:16px;background-image:url(spinner-2x.gif);background-size:16px 16px;background-repeat:no-repeat;background-position:0 0;position:absolute;right:-30px;top:5px}.delete-action{color:#a00;-webkit-transition:all .3s ease;transition:all .3s ease}.delete-action:hover .delete-action:focus{color:red;-webkit-transition:all .3s ease;transition:all .3s ease}.strikethrough{text-decoration:line-through}.hmbkp-exclude-settings td:first-child,.hmbkp-exclude-settings th:first-child{width:20px;padding-right:0}.hmbkp-exclude-settings table .button-secondary{line-height:18px;height:20px}thead td{border-bottom:1px solid #e1e1e1}.hmbkp-exclude-settings table .spinner{display:block;float:left;margin:0}.column-filesize code{position:relative}.column-filesize .dashicons-update{display:none;overflow:hidden;position:absolute;width:100%;left:0;text-align:center;background-color:rgba(255,255,255,.8)}.column-filesize .dashicons-update span{display:none}.column-filesize:hover .dashicons-update{display:inline-block}.hmbkp-exclude-settings td span.reason{color:#CCC}.server-info{overflow:auto;max-height:50%;outline:#000 solid 1px}.server-info pre{max-height:100px;overflow-x:hidden}.page-title-action span.dashicons-admin-users{position:relative;display:inline-block;vertical-align:middle;top:-2px}pre{background-color:#eee;padding:10px;white-space:pre;max-height:320px;overflow:auto;word-wrap:normal!important}@media screen and (max-width:768px){.wrap h2{padding:10px 0 0}.hmbkp-schedule-sentence::before{height:80px}h2 .nav-tab{display:block;padding:10px;margin:0}#intercom-info,.hmbkp-exclude-settings tr>:first-child,.hmbkp-schedule-settings thead tr:nth-child(2),.hmbkp-schedule-settings tr :nth-child(4),.hmbkp-schedule-settings tr :nth-child(5){display:none}.hmbkp-schedule-sentence{margin:10px 0;padding:10px}.hmbkp-exclude-settings table{margin:0 -10px;border-left:none;border-right:none;width:calc(100% + 20px)}.hmbkp-schedule-settings{padding:0 10px 10px;margin-left:-10px;margin-right:-10px;margin-bottom:-10px}table.widefat tbody tr:nth-child(even){background-color:#fff}table.widefat tbody tr:nth-child(odd){background-color:#f9f9f9}}
1
+ .hmbkp-schedule-actions a,.hmbkp-schedule-settings .column-format code{white-space:nowrap}.hmbkp_active td:first-child>code:before{content:"\00a0 \2713 ";font-size:11px}.hmbkp_active{background:#E5F7E8}div#hmbkp-warning,h2.nav-tab-wrapper+div[id^=hmbkp]{margin:20px 0 15px}h2+div[id^=hmbkp] input{max-width:100%}li a.hmbkp-running:not(.current):before{width:20px;height:20px;margin:-1px 10px -5px 0;content:"";background:url(spinner-2x.gif) no-repeat;background-size:20px;display:inline-block}.hmbkp-upsell{margin-top:40px;padding-top:16px;border-top:1px solid #ccc}.hmbkp-upsell a{color:#57792b}.hmbkp-upsell a:hover{color:#98c063}.hmbkp-upsell-sep{color:#bbb}.hmbkp-upsell ul{overflow:hidden}.hmbkp-upsell li{float:left;margin:0 20px 20px 0}.hmbkp-upsell img{display:block;margin:0 auto;max-width:120px;min-height:60px}.hmbkp-upsell ul a{display:block;margin-bottom:0;width:120px}.hmbkp-upsell .howto{font-weight:400;display:inline}.hmbkp-upsell .hmbkp_hide{float:right}.hmbkp-schedule-sentence{font-size:16px;font-weight:lighter;margin:0 0 20px;background-color:#FBFBFB;padding:20px;border:1px solid #e5e5e5;box-shadow:0 1px 1px rgba(0,0,0,.04)}.hmbkp-schedule-sentence::before{content:"\2714";margin-right:10px;width:16px;height:60px;display:block;float:left}.hmbkp-schedule-sentence.hmbkp-error:before{content:"\2718"}.hmbkp-schedule-sentence.hmbkp-running:before{width:20px;height:80px;margin:-1px 10px 0 0;content:"";background:url(spinner-2x.gif) no-repeat;background-size:20px;display:inline-block}.hmbkp-schedule-sentence .hmbkp-status{display:none;font-size:12px;color:#666;margin:2px 0 0 30px}.hmbkp-schedule-sentence.hmbkp-running .hmbkp-status{display:block}.hmbkp-schedule-sentence.hmbkp-running .hmbkp-schedule-actions{display:none}.hmbkp-schedule-sentence :not(a)[title]{border-bottom:1px dotted #CCC;cursor:help}.hmbkp-schedule-sentence .hmbkp-status[title]{border-bottom:none}.hmbkp-schedule-sentence .submit{padding:0}.hmbkp-schedule-sentence .hmbkp-schedule-actions{visibility:visible;font-size:12px;font-weight:400;margin:0 0 0 26px}.hmbkp-schedule-sentence .row-actions{position:static}.hmbkp-schedule-settings{border-top:1px solid #e5e5e5;margin:20px -20px -20px;background-color:#f5f5f5;padding:0 20px 20px}.hmbkp-exclude-settings thead tr:last-child,table.widefat tbody tr:nth-child(odd){background-color:#f9f9f9}.hmbkp-ajax-loading,button.hmbkp-ajax-loading{padding-left:20px;position:relative}.hmbkp-ajax-loading::after{content:"";width:16px;height:16px;background-image:url(spinner-2x.gif);background-size:16px 16px;background-repeat:no-repeat;background-position:0 0;position:absolute;right:-30px;top:5px}.delete-action{color:#a00;-webkit-transition:all .3s ease;transition:all .3s ease}.delete-action:hover .delete-action:focus{color:red;-webkit-transition:all .3s ease;transition:all .3s ease}.strikethrough{text-decoration:line-through}.hmbkp-exclude-settings td:first-child,.hmbkp-exclude-settings th:first-child{width:20px;padding-right:0}.hmbkp-exclude-settings table .button-secondary{line-height:18px;height:20px}thead td{border-bottom:1px solid #e1e1e1}.hmbkp-exclude-settings table .spinner{display:block;float:left;margin:0}.column-filesize code{position:relative}.column-filesize .dashicons-update{display:none;overflow:hidden;position:absolute;width:100%;left:0;text-align:center;background-color:rgba(255,255,255,.8)}.column-filesize .dashicons-update span{display:none}.column-filesize:hover .dashicons-update{display:inline-block}.hmbkp-exclude-settings td span.reason{color:#CCC}.server-info{overflow:auto;max-height:50%;outline:#000 solid 1px}.server-info pre{max-height:100px;overflow-x:hidden}.page-title-action span.dashicons-admin-users{position:relative;display:inline-block;vertical-align:middle;top:-2px}pre{background-color:#eee;padding:10px;white-space:pre;max-height:320px;overflow:auto;word-wrap:normal!important}@media screen and (max-width:768px){.wrap h2{padding:10px 0 0}.hmbkp-schedule-sentence::before{height:80px}h2 .nav-tab{display:block;padding:10px;margin:0}#intercom-info,.hmbkp-exclude-settings tr>:first-child,.hmbkp-schedule-settings thead tr:nth-child(2),.hmbkp-schedule-settings tr :nth-child(4),.hmbkp-schedule-settings tr :nth-child(5){display:none}.hmbkp-schedule-sentence{margin:10px 0;padding:10px}.hmbkp-exclude-settings table{margin:0 -10px;border-left:none;border-right:none;width:calc(100% + 20px)}.hmbkp-schedule-settings{padding:0 10px 10px;margin-left:-10px;margin-right:-10px;margin-bottom:-10px}table.widefat tbody tr:nth-child(even){background-color:#fff}table.widefat tbody tr:nth-child(odd){background-color:#f9f9f9}}.tools_page_backupwordpress_extensions a[href*="page=backupwordpress"]{font-weight:700!important;color:#fff!important}
assets/hmbkp.min.js CHANGED
@@ -1,2 +1,2 @@
1
- var BackUpWordPressAdmin=function(a){"use strict";function b(){d=a("select#hmbkp_schedule_recurrence_type"),a.ajaxSetup({cache:!1}),d.length&&(c(d.val()),a(document).on("change","select#hmbkp_schedule_recurrence_type",function(){c(a(this).val())})),a(document).on("click",".hmbkp-schedule-actions .delete-action",function(a){confirm(hmbkp.delete_schedule)||a.preventDefault()}),a(document).on("click",".hmbkp_manage_backups_row .delete-action",function(a){confirm(hmbkp.delete_backup)||a.preventDefault()}),a(document).on("click",".hmbkp-edit-schedule-excludes-form .delete-action",function(a){confirm(hmbkp.remove_exclude_rule)||a.preventDefault()}),a.post(ajaxurl,{nonce:hmbkp.nonce,action:"hmbkp_cron_test"},function(b){"1"!==b&&a(".wrap > h2").after(b)}),a(document).on("click",".hmbkp-run",function(b){wp.heartbeat.interval("fast"),a(this).closest(".hmbkp-schedule-sentence").addClass("hmbkp-running"),a(".hmbkp-error").removeClass("hmbkp-error");var c=a("[data-hmbkp-schedule-id]").attr("data-hmbkp-schedule-id");a.post(ajaxurl,{hmbkp_run_schedule_nonce:hmbkp.hmbkp_run_schedule_nonce,action:"hmbkp_run_schedule",hmbkp_schedule_id:c}),b.preventDefault()}),a(document).on("heartbeat-send",function(b,c){c.hmbkp_schedule_id=a("[data-hmbkp-schedule-id]").attr("data-hmbkp-schedule-id"),a(".hmbkp-schedule-sentence.hmbkp-running").length?c.hmbkp_is_in_progress=!0:c.hmbkp_client_request="site_size"}),a(document).on("heartbeat-tick",function(b,c){if(0!==c.hmbkp_schedule_status||a(".hmbkp-error").length||location.reload(!0),0!==c.hmbkp_schedule_status&&void 0!==c.hmbkp_schedule_status&&a(".hmbkp-status").replaceWith(c.hmbkp_schedule_status),void 0!==c.hmbkp_site_size&&a("code.calculating").length){a("code.calculating").text(c.hmbkp_site_size);var d=a(".hmbkp-exclude-settings");d.length&&d.replaceWith(c.hmbkp_dir_sizes)}}),a(document).on("click",".hmbkp-thickbox-close",function(a){a.preventDefault(),window.parent.tb_remove()}),a(document).on("click","#hmbkp-warning-backup .notice-dismiss",function(){a.post(ajaxurl,{action:"hmbkp_dismiss_error"})}),jQuery(document).one("click",".hmbkp_send_error_via_email",function(a){a.preventDefault(),jQuery(this).addClass("hmbkp-ajax-loading").attr("disabled","disabled"),jQuery.post(ajaxurl,{nonce:hmbkp.nonce,action:"hmbkp_email_error",hmbkp_error:data},function(){})})}function c(a){a="undefined"!=typeof a?a:"manually";var b=jQuery(".recurring-setting"),c=jQuery("#schedule-start"),d=jQuery(".twice-js");switch(a){case"manually":b.hide();break;case"hourly":b.hide();break;case"daily":b.hide(),c.show(),d.hide();break;case"twicedaily":b.hide(),c.show(),d.show();break;case"weekly":// fall through
2
  case"fortnightly":b.hide(),jQuery("#start-day").show(),c.show(),d.hide();break;case"monthly":b.hide(),c.show(),jQuery("#start-date").show(),d.hide()}}var d;return{init:b}}(jQuery);jQuery(document).ready(BackUpWordPressAdmin.init);
1
+ var BackUpWordPressAdmin=function(a){"use strict";function b(){d=a("select#hmbkp_schedule_recurrence_type"),a.ajaxSetup({cache:!1}),d.length&&(c(d.val()),a(document).on("change","select#hmbkp_schedule_recurrence_type",function(){c(a(this).val())})),a(".notice.is-dismissible").on("click",".notice-dismiss",function(){a.post(ajaxurl,{action:"hmbkp_dismiss_notice"})}),a(document).on("click",".hmbkp-schedule-actions .delete-action",function(a){confirm(hmbkp.delete_schedule)||a.preventDefault()}),a(document).on("click",".hmbkp_manage_backups_row .delete-action",function(a){confirm(hmbkp.delete_backup)||a.preventDefault()}),a(document).on("click",".hmbkp-edit-schedule-excludes-form .delete-action",function(a){confirm(hmbkp.remove_exclude_rule)||a.preventDefault()}),a.post(ajaxurl,{nonce:hmbkp.nonce,action:"hmbkp_cron_test"},function(b){"1"!==b&&a(".wrap > h2").after(b)}),a(document).on("click",".hmbkp-run",function(b){wp.heartbeat.interval("fast"),a(this).closest(".hmbkp-schedule-sentence").addClass("hmbkp-running"),a(".hmbkp-error").removeClass("hmbkp-error");var c=a("[data-hmbkp-schedule-id]").attr("data-hmbkp-schedule-id");a.post(ajaxurl,{hmbkp_run_schedule_nonce:hmbkp.hmbkp_run_schedule_nonce,action:"hmbkp_run_schedule",hmbkp_schedule_id:c}),b.preventDefault()}),a(document).on("heartbeat-send",function(b,c){c.hmbkp_schedule_id=a("[data-hmbkp-schedule-id]").attr("data-hmbkp-schedule-id"),a(".hmbkp-schedule-sentence.hmbkp-running").length?c.hmbkp_is_in_progress=!0:c.hmbkp_client_request="site_size"}),a(document).on("heartbeat-tick",function(b,c){if(0!==c.hmbkp_schedule_status||a(".hmbkp-error").length||location.reload(!0),0!==c.hmbkp_schedule_status&&void 0!==c.hmbkp_schedule_status&&a(".hmbkp-status").replaceWith(c.hmbkp_schedule_status),void 0!==c.hmbkp_site_size&&a("code.calculating").length){a("code.calculating").text(c.hmbkp_site_size);var d=a(".hmbkp-exclude-settings");d.length&&d.replaceWith(c.hmbkp_dir_sizes)}}),a(document).on("click",".hmbkp-thickbox-close",function(a){a.preventDefault(),window.parent.tb_remove()}),a(document).on("click",'[id^="hmbkp-warning-"] .notice-dismiss',function(){a.post(ajaxurl,{action:"hmbkp_dismiss_error"})}),jQuery(document).one("click",".hmbkp_send_error_via_email",function(a){a.preventDefault(),jQuery(this).addClass("hmbkp-ajax-loading").attr("disabled","disabled"),jQuery.post(ajaxurl,{nonce:hmbkp.nonce,action:"hmbkp_email_error",hmbkp_error:data},function(){})})}function c(a){a="undefined"!=typeof a?a:"manually";var b=jQuery(".recurring-setting"),c=jQuery("#schedule-start"),d=jQuery(".twice-js");switch(a){case"manually":b.hide();break;case"hourly":b.hide();break;case"daily":b.hide(),c.show(),d.hide();break;case"twicedaily":b.hide(),c.show(),d.show();break;case"weekly":// fall through
2
  case"fortnightly":b.hide(),jQuery("#start-day").show(),c.show(),d.hide();break;case"monthly":b.hide(),c.show(),jQuery("#start-date").show(),d.hide()}}var d;return{init:b}}(jQuery);jQuery(document).ready(BackUpWordPressAdmin.init);
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.5
7
  Author: Human Made Limited
8
  Author URI: http://hmn.md/
9
  License: GPL-2+
@@ -51,7 +51,5 @@ if ( HMBKP_Setup::meets_requirements() ) {
51
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-plugin.php' );
52
  } else {
53
  add_action( 'admin_init', array( 'HMBKP_Setup', 'self_deactivate' ) );
54
-
55
  add_action( 'all_admin_notices', array( 'HMBKP_Setup', 'display_admin_notices' ) );
56
  }
57
-
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.6.0
7
  Author: Human Made Limited
8
  Author URI: http://hmn.md/
9
  License: GPL-2+
51
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-plugin.php' );
52
  } else {
53
  add_action( 'admin_init', array( 'HMBKP_Setup', 'self_deactivate' ) );
 
54
  add_action( 'all_admin_notices', array( 'HMBKP_Setup', 'display_admin_notices' ) );
55
  }
 
classes/backup/class-backup-engine-database-imysqldump.php CHANGED
@@ -51,7 +51,7 @@ class IMysqldump_Database_Backup_Engine extends Database_Backup_Engine {
51
  return apply_filters( 'hmbkp_imysqldump_command', array(
52
  'default-character-set' => $this->get_charset(),
53
  'hex-blob' => true,
54
- 'single-transaction' => defined( 'HMBKP_MYSQLDUMP_SINGLE_TRANSACTION' ) && HMBKP_MYSQLDUMP_SINGLE_TRANSACTION
55
  ) );
56
 
57
  }
@@ -69,14 +69,11 @@ class IMysqldump_Database_Backup_Engine extends Database_Backup_Engine {
69
 
70
  if ( $this->get_host() && $this->get_port() ) {
71
  $dsn = 'mysql:host=' . $this->get_host() . ';port=' . $this->get_port() . ';dbname=' . $this->get_name();
72
- }
73
-
74
- elseif ( $this->get_socket() ) {
75
  $dsn = 'mysql:unix_socket=' . $this->get_socket() . ';dbname=' . $this->get_name();
76
  }
77
 
78
  return $dsn;
79
 
80
  }
81
-
82
  }
51
  return apply_filters( 'hmbkp_imysqldump_command', array(
52
  'default-character-set' => $this->get_charset(),
53
  'hex-blob' => true,
54
+ 'single-transaction' => defined( 'HMBKP_MYSQLDUMP_SINGLE_TRANSACTION' ) && HMBKP_MYSQLDUMP_SINGLE_TRANSACTION,
55
  ) );
56
 
57
  }
69
 
70
  if ( $this->get_host() && $this->get_port() ) {
71
  $dsn = 'mysql:host=' . $this->get_host() . ';port=' . $this->get_port() . ';dbname=' . $this->get_name();
72
+ } elseif ( $this->get_socket() ) {
 
 
73
  $dsn = 'mysql:unix_socket=' . $this->get_socket() . ';dbname=' . $this->get_name();
74
  }
75
 
76
  return $dsn;
77
 
78
  }
 
79
  }
classes/backup/class-backup-engine-file-zip-archive.php CHANGED
@@ -27,10 +27,7 @@ class Zip_Archive_File_Backup_Engine extends File_Backup_Engine {
27
  // Create an empty directory for each directory in the filesystem
28
  if ( $file->isDir() ) {
29
  $zip->addEmptyDir( $file->getRelativePathname() );
30
- }
31
-
32
- // Archive the file with a relative path
33
- elseif ( $file->isFile() ) {
34
  $zip->addFile( $file->getPathname(), $file->getRelativePathname() );
35
  }
36
  }
@@ -40,9 +37,11 @@ class Zip_Archive_File_Backup_Engine extends File_Backup_Engine {
40
  $this->warning( __CLASS__, $zip->status );
41
  }
42
 
 
43
  if ( $zip->statusSys ) {
44
  $this->warning( __CLASS__, $zip->statusSys );
45
  }
 
46
 
47
  $zip->close();
48
 
@@ -51,5 +50,4 @@ class Zip_Archive_File_Backup_Engine extends File_Backup_Engine {
51
  return $this->verify_backup();
52
 
53
  }
54
-
55
  }
27
  // Create an empty directory for each directory in the filesystem
28
  if ( $file->isDir() ) {
29
  $zip->addEmptyDir( $file->getRelativePathname() );
30
+ } elseif ( $file->isFile() ) { // Archive the file with a relative path
 
 
 
31
  $zip->addFile( $file->getPathname(), $file->getRelativePathname() );
32
  }
33
  }
37
  $this->warning( __CLASS__, $zip->status );
38
  }
39
 
40
+ // @codingStandardsIgnoreStart
41
  if ( $zip->statusSys ) {
42
  $this->warning( __CLASS__, $zip->statusSys );
43
  }
44
+ // @codingStandardsIgnoreEnd
45
 
46
  $zip->close();
47
 
50
  return $this->verify_backup();
51
 
52
  }
 
53
  }
classes/backup/class-backup-engine-file.php CHANGED
@@ -28,7 +28,7 @@ abstract class File_Backup_Engine extends Backup_Engine {
28
  $this->set_backup_filename( implode( '-', array(
29
  str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ),
30
  'backup',
31
- current_time( 'Y-m-d-H-i-s' )
32
  ) ) . '.zip' );
33
 
34
  $this->excludes = new Excludes;
28
  $this->set_backup_filename( implode( '-', array(
29
  str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ),
30
  'backup',
31
+ current_time( 'Y-m-d-H-i-s' ),
32
  ) ) . '.zip' );
33
 
34
  $this->excludes = new Excludes;
classes/backup/class-backup-engine.php CHANGED
@@ -111,7 +111,7 @@ abstract class Backup_Engine {
111
  }
112
 
113
  // Ensure we don't store duplicate errors by md5'ing the error as the key
114
- $this->errors[ $context ][ $_key = md5( implode( ':', (array) $error ) ) ] = $error;
115
 
116
  }
117
 
@@ -150,7 +150,7 @@ abstract class Backup_Engine {
150
  }
151
 
152
  // Ensure we don't store duplicate warnings by md5'ing the error as the key
153
- $this->warnings[ $context ][ $_key = md5( implode( ':', (array) $warning ) ) ] = $warning;
154
 
155
  }
156
 
@@ -168,7 +168,7 @@ abstract class Backup_Engine {
168
  public function error_handler( $type ) {
169
 
170
  // Skip strict & deprecated warnings
171
- if ( ( defined( 'E_DEPRECATED' ) && $type === E_DEPRECATED ) || ( defined( 'E_STRICT' ) && $type === E_STRICT ) || error_reporting() === 0 ) {
172
  return false;
173
  }
174
 
@@ -193,5 +193,4 @@ abstract class Backup_Engine {
193
  return false;
194
 
195
  }
196
-
197
  }
111
  }
112
 
113
  // Ensure we don't store duplicate errors by md5'ing the error as the key
114
+ $this->errors[ $context ][ md5( implode( ':', (array) $error ) ) ] = $error;
115
 
116
  }
117
 
150
  }
151
 
152
  // Ensure we don't store duplicate warnings by md5'ing the error as the key
153
+ $this->warnings[ $context ][ md5( implode( ':', (array) $warning ) ) ] = $warning;
154
 
155
  }
156
 
168
  public function error_handler( $type ) {
169
 
170
  // Skip strict & deprecated warnings
171
+ if ( ( defined( 'E_DEPRECATED' ) && E_DEPRECATED === $type ) || ( defined( 'E_STRICT' ) && E_STRICT === $type ) || 0 === error_reporting() ) {
172
  return false;
173
  }
174
 
193
  return false;
194
 
195
  }
 
196
  }
classes/backup/class-backup-status.php CHANGED
@@ -7,114 +7,113 @@ namespace HM\BackUpWordPress;
7
  */
8
  class Backup_Status {
9
 
10
- private $filename = '';
11
 
12
- public function __construct( $id ) {
13
- $this->id = $id;
14
- }
15
-
16
- public function start( $backup_filename, $status_message ) {
17
- $this->filename = $backup_filename;
18
- $this->set_status( $status_message );
19
- }
20
-
21
- public function get_backup_filename() {
22
-
23
- if ( $this->is_started() ) {
24
- $status = json_decode( file_get_contents( $this->get_status_filepath() ) );
25
-
26
- if ( ! empty( $status->filename ) ) {
27
- $this->filename = $status->filename;
28
- }
29
- }
30
-
31
- return $this->filename;
32
- }
33
-
34
- public function is_started() {
35
- return (bool) file_exists( $this->get_status_filepath() );
36
- }
37
-
38
- public function finish() {
39
- // Delete the backup running file
40
- if ( file_exists( $this->get_status_filepath() ) ) {
41
- unlink( $this->get_status_filepath() );
42
- }
43
- }
44
-
45
- /**
46
- * Get the status of the running backup.
47
- *
48
- * @return string
49
- */
50
- public function get_status() {
51
-
52
- if ( ! file_exists( $this->get_status_filepath() ) ) {
53
- return '';
54
- }
55
-
56
- $status = json_decode( file_get_contents( $this->get_status_filepath() ) );
57
-
58
- if ( ! empty( $status->status ) ) {
59
- return $status->status;
60
- }
61
-
62
- return '';
63
-
64
- }
65
-
66
- /**
67
- * Set the status of the running backup
68
- *
69
- * @param string $message
70
- *
71
- * @return null
72
- */
73
- public function set_status( $message ) {
74
-
75
- // If start hasn't been called yet then we wont' have a backup filename
76
- if ( ! $this->filename ) {
77
- return '';
78
- }
79
-
80
- $status = json_encode( (object) array(
81
- 'filename' => $this->filename,
82
- 'started' => $this->get_start_time(),
83
- 'status' => $message,
84
- ) );
85
-
86
- file_put_contents( $this->get_status_filepath(), $status );
87
-
88
- }
89
-
90
- /**
91
- * Get the time that the current running backup was started
92
- *
93
- * @return int $timestamp
94
- */
95
- public function get_start_time() {
96
-
97
- if ( ! file_exists( $this->get_status_filepath() ) ) {
98
- return 0;
99
- }
100
-
101
- $status = json_decode( file_get_contents( $this->get_status_filepath() ) );
102
-
103
- if ( ! empty( $status->started ) && (int) (string) $status->started === $status->started ) {
104
- return $status->started;
105
- }
106
-
107
- return time();
108
-
109
- }
110
-
111
- /**
112
- * Get the path to the backup running file that stores the running backup status
113
- *
114
- * @return string
115
- */
116
- public function get_status_filepath() {
117
- return Path::get_path() . '/.backup-' . $this->id . '-running';
118
- }
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  }
7
  */
8
  class Backup_Status {
9
 
10
+ private $filename = '';
11
 
12
+ public function __construct( $id ) {
13
+ $this->id = $id;
14
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ public function start( $backup_filename, $status_message ) {
17
+ $this->filename = $backup_filename;
18
+ $this->set_status( $status_message );
19
+ }
20
+
21
+ public function get_backup_filename() {
22
+
23
+ if ( $this->is_started() ) {
24
+ $status = json_decode( file_get_contents( $this->get_status_filepath() ) );
25
+
26
+ if ( ! empty( $status->filename ) ) {
27
+ $this->filename = $status->filename;
28
+ }
29
+ }
30
+
31
+ return $this->filename;
32
+ }
33
+
34
+ public function is_started() {
35
+ return (bool) file_exists( $this->get_status_filepath() );
36
+ }
37
+
38
+ public function finish() {
39
+ // Delete the backup running file
40
+ if ( file_exists( $this->get_status_filepath() ) ) {
41
+ unlink( $this->get_status_filepath() );
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Get the status of the running backup.
47
+ *
48
+ * @return string
49
+ */
50
+ public function get_status() {
51
+
52
+ if ( ! file_exists( $this->get_status_filepath() ) ) {
53
+ return '';
54
+ }
55
+
56
+ $status = json_decode( file_get_contents( $this->get_status_filepath() ) );
57
+
58
+ if ( ! empty( $status->status ) ) {
59
+ return $status->status;
60
+ }
61
+
62
+ return '';
63
+
64
+ }
65
+
66
+ /**
67
+ * Set the status of the running backup
68
+ *
69
+ * @param string $message
70
+ *
71
+ * @return null
72
+ */
73
+ public function set_status( $message ) {
74
+
75
+ // If start hasn't been called yet then we wont' have a backup filename
76
+ if ( ! $this->filename ) {
77
+ return '';
78
+ }
79
+
80
+ $status = json_encode( (object) array(
81
+ 'filename' => $this->filename,
82
+ 'started' => $this->get_start_time(),
83
+ 'status' => $message,
84
+ ) );
85
+
86
+ file_put_contents( $this->get_status_filepath(), $status );
87
+
88
+ }
89
+
90
+ /**
91
+ * Get the time that the current running backup was started
92
+ *
93
+ * @return int $timestamp
94
+ */
95
+ public function get_start_time() {
96
+
97
+ if ( ! file_exists( $this->get_status_filepath() ) ) {
98
+ return 0;
99
+ }
100
+
101
+ $status = json_decode( file_get_contents( $this->get_status_filepath() ) );
102
+
103
+ if ( ! empty( $status->started ) && (int) (string) $status->started === $status->started ) {
104
+ return $status->started;
105
+ }
106
+
107
+ return time();
108
+
109
+ }
110
+
111
+ /**
112
+ * Get the path to the backup running file that stores the running backup status
113
+ *
114
+ * @return string
115
+ */
116
+ public function get_status_filepath() {
117
+ return Path::get_path() . '/.backup-' . $this->id . '-running';
118
+ }
119
  }
classes/backup/class-backup.php CHANGED
@@ -39,11 +39,11 @@ class Backup {
39
 
40
  Path::get_instance()->cleanup();
41
 
42
- if ( $this->type !== 'file' ) {
43
  $this->backup_database();
44
  }
45
 
46
- if ( $this->type !== 'database' ) {
47
  $this->backup_files();
48
  }
49
 
@@ -59,12 +59,12 @@ class Backup {
59
 
60
  $database_backup_engines = apply_filters( 'hmbkp_database_backup_engines', array(
61
  new Mysqldump_Database_Backup_Engine,
62
- new IMysqldump_Database_Backup_Engine
63
  ) );
64
 
65
  // Set the file backup engine settings
66
  if ( $this->database_dump_filename ) {
67
- foreach( $database_backup_engines as &$backup_engine ) {
68
  $backup_engine->set_backup_filename( $this->database_dump_filename );
69
  }
70
  }
@@ -79,11 +79,11 @@ class Backup {
79
  // Fire up the file backup engines
80
  $file_backup_engines = apply_filters( 'hmbkp_file_backup_engines', array(
81
  new Zip_File_Backup_Engine,
82
- new Zip_Archive_File_Backup_Engine
83
  ) );
84
 
85
  // Set the file backup engine settings
86
- foreach( $file_backup_engines as &$backup_engine ) {
87
  $backup_engine->set_backup_filename( $this->backup_filename );
88
  $backup_engine->set_excludes( new Excludes( array( '*.zip', 'index.html', '.htaccess', '.*-running', '.files' ) ) );
89
  }
@@ -114,11 +114,11 @@ class Backup {
114
  // Fire up the file backup engines
115
  $backup_engines = apply_filters( 'hmbkp_file_backup_engines', array(
116
  new Zip_File_Backup_Engine,
117
- new Zip_Archive_File_Backup_Engine
118
  ) );
119
 
120
  // Set the file backup engine settings
121
- foreach( $backup_engines as &$backup_engine ) {
122
  $backup_engine->set_backup_filename( $this->backup_filename );
123
  if ( $this->excludes ) {
124
  $backup_engine->set_excludes( $this->excludes );
@@ -138,16 +138,25 @@ class Backup {
138
  * we find one which works. If a backup filename or any excludes have been
139
  * set then those are passed to each Backup_Engine.
140
  */
141
- public function perform_backup( Array $backup_engines ) {
142
 
143
  foreach ( $backup_engines as $backup_engine ) {
144
 
 
 
 
 
 
145
  if ( $backup_engine->backup() ) {
146
- $this->warnings = array_merge( $this->warnings, $backup_engine->get_warnings() );
 
147
  return $backup_engine;
148
  }
 
 
149
  $this->warnings = array_merge( $this->warnings, $backup_engine->get_warnings() );
150
- $this->errors = array_merge( $this->errors, $backup_engine->get_errors() );
 
151
  }
152
 
153
  return false;
@@ -178,12 +187,14 @@ class Backup {
178
  }
179
 
180
  // Ensure we don't store duplicate warnings by md5'ing the error as the key
181
- $this->warnings[ $context ][ $_key = md5( implode( ':', (array) $warning ) ) ] = $warning;
182
 
183
  }
184
 
185
  /**
186
- * Back compat with old error mathod
 
 
187
  *
188
  * @deprecated 3.4 Backup->warning( $context, $warning )
189
  */
@@ -204,11 +215,10 @@ class Backup {
204
  * Back compat with old method name
205
  *
206
  * @see Backup::get_backup_filepath()
207
- * @deprecated 3.4 Use Backup::get_backup_filepath()
208
  */
209
  public function get_archive_filepath() {
210
  _deprecated_function( __FUNCTION__, '3.4', 'get_backup_filepath()' );
211
  return $this->get_backup_filepath();
212
  }
213
-
214
  }
39
 
40
  Path::get_instance()->cleanup();
41
 
42
+ if ( 'file' !== $this->type ) {
43
  $this->backup_database();
44
  }
45
 
46
+ if ( 'database' !== $this->type ) {
47
  $this->backup_files();
48
  }
49
 
59
 
60
  $database_backup_engines = apply_filters( 'hmbkp_database_backup_engines', array(
61
  new Mysqldump_Database_Backup_Engine,
62
+ new IMysqldump_Database_Backup_Engine,
63
  ) );
64
 
65
  // Set the file backup engine settings
66
  if ( $this->database_dump_filename ) {
67
+ foreach ( $database_backup_engines as &$backup_engine ) {
68
  $backup_engine->set_backup_filename( $this->database_dump_filename );
69
  }
70
  }
79
  // Fire up the file backup engines
80
  $file_backup_engines = apply_filters( 'hmbkp_file_backup_engines', array(
81
  new Zip_File_Backup_Engine,
82
+ new Zip_Archive_File_Backup_Engine,
83
  ) );
84
 
85
  // Set the file backup engine settings
86
+ foreach ( $file_backup_engines as &$backup_engine ) {
87
  $backup_engine->set_backup_filename( $this->backup_filename );
88
  $backup_engine->set_excludes( new Excludes( array( '*.zip', 'index.html', '.htaccess', '.*-running', '.files' ) ) );
89
  }
114
  // Fire up the file backup engines
115
  $backup_engines = apply_filters( 'hmbkp_file_backup_engines', array(
116
  new Zip_File_Backup_Engine,
117
+ new Zip_Archive_File_Backup_Engine,
118
  ) );
119
 
120
  // Set the file backup engine settings
121
+ foreach ( $backup_engines as &$backup_engine ) {
122
  $backup_engine->set_backup_filename( $this->backup_filename );
123
  if ( $this->excludes ) {
124
  $backup_engine->set_excludes( $this->excludes );
138
  * we find one which works. If a backup filename or any excludes have been
139
  * set then those are passed to each Backup_Engine.
140
  */
141
+ public function perform_backup( array $backup_engines ) {
142
 
143
  foreach ( $backup_engines as $backup_engine ) {
144
 
145
+ /**
146
+ * If the backup_engine completes the backup then we
147
+ * clear any errors or warnings from previously failed backup_engines
148
+ * and return the successful one.
149
+ */
150
  if ( $backup_engine->backup() ) {
151
+ $this->errors = array();
152
+ $this->warnings = $backup_engine->get_warnings();
153
  return $backup_engine;
154
  }
155
+
156
+ // Store all the errors and warnings as they are shown if all engines fail
157
  $this->warnings = array_merge( $this->warnings, $backup_engine->get_warnings() );
158
+ $this->errors = array_merge( $this->errors, $backup_engine->get_errors() );
159
+
160
  }
161
 
162
  return false;
187
  }
188
 
189
  // Ensure we don't store duplicate warnings by md5'ing the error as the key
190
+ $this->warnings[ $context ][ md5( implode( ':', (array) $warning ) ) ] = $warning;
191
 
192
  }
193
 
194
  /**
195
+ * Back compat with old error method
196
+ *
197
+ * Only the backup engines themselves can fire fatal errors
198
  *
199
  * @deprecated 3.4 Backup->warning( $context, $warning )
200
  */
215
  * Back compat with old method name
216
  *
217
  * @see Backup::get_backup_filepath()
218
+ * @deprecated 3.4 Use Backup::get_backup_filepath()
219
  */
220
  public function get_archive_filepath() {
221
  _deprecated_function( __FUNCTION__, '3.4', 'get_backup_filepath()' );
222
  return $this->get_backup_filepath();
223
  }
 
224
  }
classes/class-backupwordpress-wp-cli-command.php CHANGED
@@ -87,7 +87,7 @@ class CLI extends \WP_CLI_Command {
87
  }
88
 
89
  if ( ! empty( $assoc_args['excludes'] ) ) {
90
- $hm_backup->set_excludes( $assoc_args['excludes'] );
91
  }
92
 
93
  $hm_backup->run();
@@ -99,7 +99,6 @@ class CLI extends \WP_CLI_Command {
99
  }
100
 
101
  }
102
-
103
  }
104
 
105
  \WP_CLI::add_command( 'backupwordpress', 'HM\BackUpWordPress\CLI' );
87
  }
88
 
89
  if ( ! empty( $assoc_args['excludes'] ) ) {
90
+ $hm_backup->set_excludes( new Excludes( $assoc_args['excludes'] ) );
91
  }
92
 
93
  $hm_backup->run();
99
  }
100
 
101
  }
 
102
  }
103
 
104
  \WP_CLI::add_command( 'backupwordpress', 'HM\BackUpWordPress\CLI' );
classes/class-email-service.php CHANGED
@@ -20,7 +20,9 @@ class Email_Service extends Service {
20
  *
21
  * @access public
22
  */
23
- public function field() { ?>
 
 
24
 
25
  <tr>
26
 
@@ -48,7 +50,9 @@ class Email_Service extends Service {
48
  return '';
49
  }
50
 
51
- public static function constant() { ?>
 
 
52
 
53
  <tr<?php if ( defined( 'HMBKP_ATTACHMENT_MAX_FILESIZE' ) ) { ?> class="hmbkp_active"<?php } ?>>
54
 
@@ -116,9 +120,7 @@ class Email_Service extends Service {
116
  if ( ! is_email( $email ) ) {
117
  $errors['email'] = sprintf( __( '%s isn\'t a valid email', 'backupwordpress' ), $email );
118
  }
119
-
120
  }
121
-
122
  }
123
 
124
  if ( ! empty( $errors['email'] ) ) {
@@ -128,7 +130,6 @@ class Email_Service extends Service {
128
  return $errors;
129
 
130
  }
131
-
132
  }
133
 
134
  /**
@@ -136,11 +137,8 @@ class Email_Service extends Service {
136
  * @return array An array of validated email address's
137
  */
138
  private function get_email_address_array() {
139
-
140
  $emails = array_map( 'trim', explode( ',', $this->get_field_value( 'email' ) ) );
141
-
142
  return array_filter( array_unique( $emails ), 'is_email' );
143
-
144
  }
145
 
146
  /**
@@ -152,7 +150,7 @@ class Email_Service extends Service {
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_backup_filepath();
158
 
@@ -201,19 +199,17 @@ class Email_Service extends Service {
201
  if ( ! $sent ) {
202
 
203
  $message = sprintf( __( 'BackUpWordPress has completed a backup of your site %1$s.', 'backupwordpress' ) . "\n\n" . __( 'Unfortunately, the backup file was too large to attach to this email.', 'backupwordpress' ) . "\n\n" . __( 'You can download the backup file by clicking the link below:', 'backupwordpress' ) . "\n\n" . '%2$s' . "\n\n" . __( "Kind Regards,\nThe Happy BackUpWordPress Backup Emailing Robot", 'backupwordpress' ), home_url(), $download );
204
-
205
  wp_mail( $this->get_email_address_array(), $subject, $message, $headers );
206
 
207
  }
208
-
209
  }
210
-
211
  }
212
 
213
- public static function intercom_data() { return array(); }
 
 
214
 
215
  public static function intercom_data_html() {}
216
-
217
  }
218
 
219
  // Register the service
20
  *
21
  * @access public
22
  */
23
+ public function field() {
24
+
25
+ ?>
26
 
27
  <tr>
28
 
50
  return '';
51
  }
52
 
53
+ public static function constant() {
54
+
55
+ ?>
56
 
57
  <tr<?php if ( defined( 'HMBKP_ATTACHMENT_MAX_FILESIZE' ) ) { ?> class="hmbkp_active"<?php } ?>>
58
 
120
  if ( ! is_email( $email ) ) {
121
  $errors['email'] = sprintf( __( '%s isn\'t a valid email', 'backupwordpress' ), $email );
122
  }
 
123
  }
 
124
  }
125
 
126
  if ( ! empty( $errors['email'] ) ) {
130
  return $errors;
131
 
132
  }
 
133
  }
134
 
135
  /**
137
  * @return array An array of validated email address's
138
  */
139
  private function get_email_address_array() {
 
140
  $emails = array_map( 'trim', explode( ',', $this->get_field_value( 'email' ) ) );
 
141
  return array_filter( array_unique( $emails ), 'is_email' );
 
142
  }
143
 
144
  /**
150
  */
151
  public function action( $action, Backup $backup ) {
152
 
153
+ if ( 'hmbkp_backup_complete' === $action && $this->get_email_address_array() ) {
154
 
155
  $file = $backup->get_backup_filepath();
156
 
199
  if ( ! $sent ) {
200
 
201
  $message = sprintf( __( 'BackUpWordPress has completed a backup of your site %1$s.', 'backupwordpress' ) . "\n\n" . __( 'Unfortunately, the backup file was too large to attach to this email.', 'backupwordpress' ) . "\n\n" . __( 'You can download the backup file by clicking the link below:', 'backupwordpress' ) . "\n\n" . '%2$s' . "\n\n" . __( "Kind Regards,\nThe Happy BackUpWordPress Backup Emailing Robot", 'backupwordpress' ), home_url(), $download );
 
202
  wp_mail( $this->get_email_address_array(), $subject, $message, $headers );
203
 
204
  }
 
205
  }
 
206
  }
207
 
208
+ public static function intercom_data() {
209
+ return array();
210
+ }
211
 
212
  public static function intercom_data_html() {}
 
213
  }
214
 
215
  // Register the service
classes/class-excludes.php CHANGED
@@ -37,7 +37,7 @@ class Excludes {
37
  'backup-db',
38
  'Envato-backups',
39
  'managewp',
40
- 'backupwordpress-*-backups'
41
  );
42
 
43
  public function __construct( $excludes = array() ) {
@@ -71,7 +71,7 @@ class Excludes {
71
  * @return array The array of exclude rules.
72
  */
73
  public function get_excludes() {
74
- return array_merge( $this->get_default_excludes(), $this->get_user_excludes() );
75
  }
76
 
77
  /**
@@ -101,7 +101,6 @@ class Excludes {
101
  $exclude = '/' . $exclude . '/';
102
 
103
  }
104
-
105
  }
106
 
107
  return $excludes;
@@ -161,19 +160,21 @@ class Excludes {
161
  */
162
  public function normalize( $excludes ) {
163
 
164
- $excludes = array_map( function( $exclude ) {
 
165
 
166
- // Convert absolute paths to relative
167
- $exclude = str_replace( PATH::get_root(), '', wp_normalize_path( $exclude ) );
168
 
169
- // Trim the slashes
170
- $exclude = trim( $exclude );
171
- $exclude = ltrim( $exclude, '/' );
172
- $exclude = untrailingslashit( $exclude );
173
 
174
- return $exclude;
175
 
176
- }, $excludes );
 
177
 
178
  // Remove duplicate or empty rules
179
  $excludes = array_unique( $excludes );
@@ -182,5 +183,4 @@ class Excludes {
182
  return $excludes;
183
 
184
  }
185
-
186
  }
37
  'backup-db',
38
  'Envato-backups',
39
  'managewp',
40
+ 'backupwordpress-*-backups',
41
  );
42
 
43
  public function __construct( $excludes = array() ) {
71
  * @return array The array of exclude rules.
72
  */
73
  public function get_excludes() {
74
+ return array_merge( $this->get_default_excludes(), $this->get_user_excludes() );
75
  }
76
 
77
  /**
101
  $exclude = '/' . $exclude . '/';
102
 
103
  }
 
104
  }
105
 
106
  return $excludes;
160
  */
161
  public function normalize( $excludes ) {
162
 
163
+ $excludes = array_map(
164
+ function( $exclude ) {
165
 
166
+ // Convert absolute paths to relative
167
+ $exclude = str_replace( PATH::get_root(), '', wp_normalize_path( $exclude ) );
168
 
169
+ // Trim the slashes
170
+ $exclude = trim( $exclude );
171
+ $exclude = ltrim( $exclude, '/' );
172
+ $exclude = untrailingslashit( $exclude );
173
 
174
+ return $exclude;
175
 
176
+ },
177
+ $excludes );
178
 
179
  // Remove duplicate or empty rules
180
  $excludes = array_unique( $excludes );
183
  return $excludes;
184
 
185
  }
 
186
  }
classes/class-extensions.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace HM\BackUpWordPress;
4
+
5
+ /**
6
+ * Class Extensions
7
+ * @package HM\BackUpWordPress
8
+ */
9
+ final class Extensions {
10
+
11
+ /**
12
+ * Contains the instantiated Extensions instance.
13
+ *
14
+ * @var Extensions $this->instance
15
+ */
16
+ private static $instance;
17
+
18
+ /**
19
+ * Holds the root URL of the API.
20
+ *
21
+ * @var string
22
+ */
23
+ protected $root_url = '';
24
+
25
+ /**
26
+ * Extensions constructor.
27
+ *
28
+ */
29
+ private function __construct() {
30
+
31
+ $this->root_url = 'https://bwp.hmn.md/wp-json/wp/v2/';
32
+
33
+ }
34
+
35
+ private function __wakeup() {}
36
+
37
+ private function __clone() {}
38
+
39
+ /**
40
+ * Returns the *Singleton* instance of this class.
41
+ *
42
+ * @staticvar Extensions $instance The *Singleton* instances of this class.
43
+ *
44
+ * @return Extensions The *Singleton* instance.
45
+ */
46
+ public static function get_instance() {
47
+
48
+ if ( ! ( self::$instance instanceof Extensions ) ) {
49
+
50
+ self::$instance = new Extensions();
51
+
52
+ }
53
+
54
+ return self::$instance;
55
+
56
+ }
57
+
58
+ /**
59
+ * Parses the body of the API response and returns it.
60
+ *
61
+ * @return array|bool|mixed|object
62
+ */
63
+ public function get_edd_data() {
64
+
65
+ $response = $this->fetch( 'edd-downloads' );
66
+
67
+ if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
68
+ return false;
69
+ }
70
+
71
+ return json_decode( $response['body'] );
72
+
73
+ }
74
+
75
+ /**
76
+ * Makes a request to the JSON API or retrieves the cached response. Caches the response for one day.
77
+ *
78
+ * @param $endpoint
79
+ * @param int $ttl
80
+ *
81
+ * @return array|mixed|\WP_Error
82
+ */
83
+ protected function fetch( $endpoint, $ttl = DAY_IN_SECONDS ) {
84
+
85
+ $request_url = $this->root_url . $endpoint;
86
+
87
+ $cache_key = md5( $request_url );
88
+
89
+ $cached = get_transient( 'bwp_' . $cache_key );
90
+
91
+ if ( $cached ) {
92
+ return $cached;
93
+ }
94
+
95
+ $response = wp_remote_get( $request_url );
96
+
97
+ if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
98
+ return new \WP_Error( 'hmbkp-error', 'Unable to fetch API response' );
99
+ }
100
+
101
+ set_transient( 'bwp_' . $cache_key, $response, $ttl );
102
+
103
+ return $response;
104
+
105
+ }
106
+
107
+ }
classes/class-notices.php CHANGED
@@ -3,70 +3,122 @@
3
  namespace HM\BackUpWordPress;
4
 
5
  /**
6
- * Class Notices
 
 
 
7
  */
8
  class Notices {
9
 
10
  /**
11
- * @var
 
 
 
 
 
12
  */
13
- private static $_instance;
14
-
15
- private $notices;
16
 
17
  /**
 
18
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  */
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;
32
 
33
  }
34
 
35
  /**
36
- * @param string $context
37
- * @param array $messages
38
- * @param bool $persistant whether to save the notices to the database
39
  *
40
- * @return mixed|void
 
 
41
  */
42
- public function set_notices( $context, array $messages, $persistant = true ) {
 
 
 
 
 
 
 
 
 
43
 
44
- $this->notices[ $context ] = $messages;
45
 
46
- if ( $persistant ) {
47
- $notices = get_option( 'hmbkp_notices' );
48
- $notices[ $context ] = $messages;
49
- update_option( 'hmbkp_notices', $notices );
 
 
 
 
 
 
 
 
 
50
  }
51
 
 
 
52
  }
53
 
54
  /**
55
- * Fetch the notices for the context.
56
- * All notices by default.
57
  *
58
- * @param string $context
 
59
  *
60
- * @return array|mixed|void
 
 
61
  */
62
  public function get_notices( $context = '' ) {
63
 
64
  $notices = $this->get_all_notices();
65
 
66
- if ( $notices ) {
67
 
68
- if ( $context && isset( $notices[ $context ] ) ) {
69
- return $notices[ $context ];
70
  }
71
 
72
  return $notices;
@@ -76,19 +128,30 @@ class Notices {
76
 
77
  }
78
 
 
 
 
 
 
79
  private function get_all_notices() {
80
- return array_merge_recursive( (array) $this->notices, (array) get_option( 'hmbkp_notices' ) );
81
  }
82
 
83
  /**
84
- * Delete all notices from the DB.
 
 
85
  */
86
- public function clear_all_notices() {
 
 
 
87
 
 
 
 
 
88
  $this->notices = array();
89
-
90
  delete_option( 'hmbkp_notices' );
91
-
92
  }
93
-
94
  }
3
  namespace HM\BackUpWordPress;
4
 
5
  /**
6
+ * Class for managing notices
7
+ *
8
+ * Notices are messages along with an associated context, by default
9
+ * they are stored in the db and thus persist between page loads.
10
  */
11
  class Notices {
12
 
13
  /**
14
+ * The array of notice messages
15
+ *
16
+ * This is a multidimensional array of
17
+ * `array( context => array( 'message' ) );``
18
+ *
19
+ * @var array
20
  */
21
+ private $notices = array();
 
 
22
 
23
  /**
24
+ * Contains the instantiated Notices instance
25
  *
26
+ * @var Notices $this->get_instance
27
+ */
28
+ private static $instance;
29
+
30
+ /**
31
+ * Protected constructor to prevent creating a new instance of the
32
+ * *Singleton* via the `new` operator from outside of this class.
33
+ */
34
+ protected function __construct() {}
35
+
36
+ /**
37
+ * Private clone method to prevent cloning of the instance of the
38
+ * *Singleton* instance.
39
  */
40
+ private function __clone() {}
41
 
42
  /**
43
+ * Private unserialize method to prevent unserializing of the *Singleton*
44
+ * instance.
45
+ */
46
+ private function __wakeup() {}
47
+
48
+ /**
49
+ * Returns the *Singleton* instance of this class.
50
+ *
51
+ * @staticvar Notices $instance The *Singleton* instances of this class.
52
+ *
53
+ * @return Notices The *Singleton* instance.
54
  */
55
  public static function get_instance() {
56
 
57
+ if ( ! ( self::$instance instanceof Notices ) ) {
58
+ self::$instance = new Notices();
59
  }
60
 
61
+ return self::$instance;
62
 
63
  }
64
 
65
  /**
66
+ * Set an array of notice messages for a specific context
 
 
67
  *
68
+ * @param string $context The context of the notice message
69
+ * @param array $messages The array of messages
70
+ * @param boolean $persistent Whether the notice should persist via the database. Defaults to true.
71
  */
72
+ public function set_notices( $context, array $messages, $persistent = true ) {
73
+
74
+ // Clear any empty messages and avoid duplicates
75
+ $messages = array_unique( array_filter( $messages ) );
76
+
77
+ if ( empty( $context ) || empty( $messages ) ) {
78
+ return false;
79
+ }
80
+
81
+ $this->notices[ $context ] = array_merge( $this->get_notices( $context ), $messages );
82
 
83
+ if ( $persistent ) {
84
 
85
+ $new_notices = $notices = $this->get_persistent_notices();
86
+
87
+ // Make sure we merge in any existing notices
88
+ if ( ! empty( $notices[ $context ] ) ) {
89
+ $new_notices[ $context ] = array_merge( $notices[ $context ], $messages );
90
+ } else {
91
+ $new_notices[ $context ] = $messages;
92
+ }
93
+
94
+ // Only update the database if the notice array has changed
95
+ if ( $new_notices !== $notices ) {
96
+ update_option( 'hmbkp_notices', $new_notices );
97
+ }
98
  }
99
 
100
+ return true;
101
+
102
  }
103
 
104
  /**
105
+ * Fetch an array of notices messages
 
106
  *
107
+ * If you specify a context then you'll just get messages for that context otherwise
108
+ * you get multidimensional array of all contexts and their messages.
109
  *
110
+ * @param string $context The context that you'd like the messages for
111
+ *
112
+ * @return array The array of notice messages
113
  */
114
  public function get_notices( $context = '' ) {
115
 
116
  $notices = $this->get_all_notices();
117
 
118
+ if ( ! empty( $notices ) ) {
119
 
120
+ if ( ! empty( $context ) ) {
121
+ return isset( $notices[ $context ] ) ? $notices[ $context ] : array();
122
  }
123
 
124
  return $notices;
128
 
129
  }
130
 
131
+ /**
132
+ * Get both standard and persistent notices
133
+ *
134
+ * @return array The array of contexts and notices
135
+ */
136
  private function get_all_notices() {
137
+ return array_map( 'array_unique', array_merge_recursive( $this->notices, $this->get_persistent_notices() ) );
138
  }
139
 
140
  /**
141
+ * Load the persistent notices from the database
142
+ *
143
+ * @return array The array of notices
144
  */
145
+ private function get_persistent_notices() {
146
+ $notices = get_option( 'hmbkp_notices' );
147
+ return ! empty( $notices ) ? $notices : array();
148
+ }
149
 
150
+ /**
151
+ * Clear all notices including persistent ones
152
+ */
153
+ public function clear_all_notices() {
154
  $this->notices = array();
 
155
  delete_option( 'hmbkp_notices' );
 
156
  }
 
157
  }
classes/class-path.php CHANGED
@@ -119,7 +119,7 @@ class Path {
119
  $base = parse_url( $slashed_home, PHP_URL_PATH );
120
  $document_root_fix = wp_normalize_path( realpath( $_SERVER['DOCUMENT_ROOT'] ) );
121
  $abspath_fix = wp_normalize_path( ABSPATH );
122
- $home_path = 0 === strpos( $abspath_fix, $document_root_fix ) ? $document_root_fix . $base : $home_path;
123
  }
124
  }
125
 
@@ -243,8 +243,7 @@ class Path {
243
  }
244
 
245
  $paths = array_merge( $default, $fallback );
246
-
247
- $paths = array_map( 'wp_normalize_path', $paths );
248
 
249
  return $paths;
250
 
@@ -399,12 +398,10 @@ class Path {
399
  // Try to move them
400
  if ( ! @rename( trailingslashit( $from ) . $file, trailingslashit( Path::get_path() ) . $file ) ) {
401
 
402
-
403
  // If we can't move them then try to copy them
404
  copy( trailingslashit( $from ) . $file, trailingslashit( Path::get_path() ) . $file );
405
 
406
  }
407
-
408
  }
409
  }
410
 
@@ -413,7 +410,7 @@ class Path {
413
  }
414
 
415
  // Delete the old directory if it's inside WP_CONTENT_DIR
416
- if ( false !== strpos( $from, WP_CONTENT_DIR ) && $from !== Path::get_path() ) {
417
  rmdirtree( $from );
418
  }
419
 
@@ -447,7 +444,7 @@ class CleanUpIterator extends \FilterIterator {
447
  public function accept() {
448
 
449
  // Don't remove existing backups
450
- if ( 'zip' === $this->current()->getExtension() ) {
451
  return false;
452
  }
453
 
119
  $base = parse_url( $slashed_home, PHP_URL_PATH );
120
  $document_root_fix = wp_normalize_path( realpath( $_SERVER['DOCUMENT_ROOT'] ) );
121
  $abspath_fix = wp_normalize_path( ABSPATH );
122
+ $home_path = strpos( $abspath_fix, $document_root_fix ) === 0 ? $document_root_fix . $base : $home_path;
123
  }
124
  }
125
 
243
  }
244
 
245
  $paths = array_merge( $default, $fallback );
246
+ $paths = array_map( 'wp_normalize_path', $paths );
 
247
 
248
  return $paths;
249
 
398
  // Try to move them
399
  if ( ! @rename( trailingslashit( $from ) . $file, trailingslashit( Path::get_path() ) . $file ) ) {
400
 
 
401
  // If we can't move them then try to copy them
402
  copy( trailingslashit( $from ) . $file, trailingslashit( Path::get_path() ) . $file );
403
 
404
  }
 
405
  }
406
  }
407
 
410
  }
411
 
412
  // Delete the old directory if it's inside WP_CONTENT_DIR
413
+ if ( false !== strpos( $from, WP_CONTENT_DIR ) && Path::get_path() !== $from ) {
414
  rmdirtree( $from );
415
  }
416
 
444
  public function accept() {
445
 
446
  // Don't remove existing backups
447
+ if ( 'zip' === pathinfo( $this->current()->getFilename(), PATHINFO_EXTENSION ) ) {
448
  return false;
449
  }
450
 
classes/class-plugin.php CHANGED
@@ -6,7 +6,7 @@ namespace HM\BackUpWordPress;
6
  * Class Plugin
7
  */
8
  final class Plugin {
9
- const PLUGIN_VERSION = '3.5';
10
 
11
  /**
12
  * @var Plugin The singleton instance.
@@ -18,6 +18,14 @@ final class Plugin {
18
  */
19
  private function __construct() {
20
  add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );
 
 
 
 
 
 
 
 
21
  }
22
 
23
  /**
@@ -172,6 +180,8 @@ final class Plugin {
172
 
173
  require_once( HMBKP_PLUGIN_PATH . 'classes/deprecated.php' );
174
 
 
 
175
  // Load the wp cli command
176
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
177
  include( HMBKP_PLUGIN_PATH . 'classes/class-backupwordpress-wp-cli-command.php' );
@@ -232,7 +242,7 @@ final class Plugin {
232
  'delete_schedule' => __( 'Are you sure you want to delete this schedule? All of its backups will also be deleted.', 'backupwordpress' ) . "\n\n" . __( '\'Cancel\' to go back, \'OK\' to delete.', 'backupwordpress' ) . "\n",
233
  'delete_backup' => __( 'Are you sure you want to delete this backup?', 'backupwordpress' ) . "\n\n" . __( '\'Cancel\' to go back, \'OK\' to delete.', 'backupwordpress' ) . "\n",
234
  'remove_exclude_rule' => __( 'Are you sure you want to remove this exclude rule?', 'backupwordpress' ) . "\n\n" . __( '\'Cancel\' to go back, \'OK\' to delete.', 'backupwordpress' ) . "\n",
235
- 'remove_old_backups' => __( 'Reducing the number of backups that are stored on this server will cause some of your existing backups to be deleted. Are you sure that\'s what you want?', 'backupwordpress' ) . "\n\n" . __( '\'Cancel\' to go back, \'OK\' to delete.', 'backupwordpress' ) . "\n"
236
  )
237
  );
238
 
@@ -290,9 +300,11 @@ final class Plugin {
290
  */
291
  protected function generate_key() {
292
 
293
- $check = apply_filters( "hmbkp_generate_key", null );
294
- if ( null !== $check )
 
295
  return $check;
 
296
 
297
  $key = array( ABSPATH, time() );
298
  $constants = array( 'AUTH_KEY', 'SECURE_AUTH_KEY', 'LOGGED_IN_KEY', 'NONCE_KEY', 'AUTH_SALT', 'SECURE_AUTH_SALT', 'LOGGED_IN_SALT', 'NONCE_SALT', 'SECRET_KEY' );
@@ -361,7 +373,7 @@ final class Plugin {
361
  */
362
  public function styles( $hook ) {
363
 
364
- if ( HMBKP_ADMIN_PAGE !== $hook ) {
365
  return;
366
  }
367
 
@@ -414,6 +426,37 @@ final class Plugin {
414
 
415
  <?php }
416
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
  }
418
 
419
  if ( is_multisite() && ! is_main_site() ) {
6
  * Class Plugin
7
  */
8
  final class Plugin {
9
+ const PLUGIN_VERSION = '3.6.0';
10
 
11
  /**
12
  * @var Plugin The singleton instance.
18
  */
19
  private function __construct() {
20
  add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );
21
+
22
+ $hide_notice = get_site_option( 'hmbkp_hide_info_notice', false );
23
+
24
+ if ( ! $hide_notice ) {
25
+ add_action( 'admin_notices', array( $this, 'display_feature_message' ) );
26
+ add_action( 'network_admin_notices', array( $this, 'display_feature_message' ) );
27
+ }
28
+
29
  }
30
 
31
  /**
180
 
181
  require_once( HMBKP_PLUGIN_PATH . 'classes/deprecated.php' );
182
 
183
+ require_once( HMBKP_PLUGIN_PATH . 'classes/class-extensions.php' );
184
+
185
  // Load the wp cli command
186
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
187
  include( HMBKP_PLUGIN_PATH . 'classes/class-backupwordpress-wp-cli-command.php' );
242
  'delete_schedule' => __( 'Are you sure you want to delete this schedule? All of its backups will also be deleted.', 'backupwordpress' ) . "\n\n" . __( '\'Cancel\' to go back, \'OK\' to delete.', 'backupwordpress' ) . "\n",
243
  'delete_backup' => __( 'Are you sure you want to delete this backup?', 'backupwordpress' ) . "\n\n" . __( '\'Cancel\' to go back, \'OK\' to delete.', 'backupwordpress' ) . "\n",
244
  'remove_exclude_rule' => __( 'Are you sure you want to remove this exclude rule?', 'backupwordpress' ) . "\n\n" . __( '\'Cancel\' to go back, \'OK\' to delete.', 'backupwordpress' ) . "\n",
245
+ 'remove_old_backups' => __( 'Reducing the number of backups that are stored on this server will cause some of your existing backups to be deleted. Are you sure that\'s what you want?', 'backupwordpress' ) . "\n\n" . __( '\'Cancel\' to go back, \'OK\' to delete.', 'backupwordpress' ) . "\n",
246
  )
247
  );
248
 
300
  */
301
  protected function generate_key() {
302
 
303
+ $check = apply_filters( 'hmbkp_generate_key', null );
304
+
305
+ if ( null !== $check ) {
306
  return $check;
307
+ }
308
 
309
  $key = array( ABSPATH, time() );
310
  $constants = array( 'AUTH_KEY', 'SECURE_AUTH_KEY', 'LOGGED_IN_KEY', 'NONCE_KEY', 'AUTH_SALT', 'SECURE_AUTH_SALT', 'LOGGED_IN_SALT', 'NONCE_SALT', 'SECRET_KEY' );
373
  */
374
  public function styles( $hook ) {
375
 
376
+ if ( 'tools_page_backupwordpress_extensions' !== $hook && HMBKP_ADMIN_PAGE !== $hook ) {
377
  return;
378
  }
379
 
426
 
427
  <?php }
428
 
429
+ public function display_feature_message() {
430
+
431
+ $current_screen = get_current_screen();
432
+
433
+ if ( ! isset( $current_screen ) ) {
434
+ return;
435
+ }
436
+
437
+ $page = is_multisite() ? HMBKP_ADMIN_PAGE . '-network' : HMBKP_ADMIN_PAGE;
438
+ if ( $current_screen->id !== $page ) {
439
+ return;
440
+ }
441
+
442
+ /* translators: %1$s and %2$s expand to anchor tags linking to the new extensions page. */
443
+ $info_message = sprintf(
444
+ __( 'Thanks for updating BackUpWordPress, why not check out %1$sour extensions?%2$s', 'backupwordpress' ),
445
+ '<a href="' . esc_url( get_settings_url( HMBKP_PLUGIN_SLUG . '_extensions' ) ) . '">',
446
+ '</a>'
447
+ );
448
+ ?>
449
+
450
+ <div id="hmbkp-info-message" class="updated notice is-dismissible">
451
+
452
+ <p><?php echo wp_kses_post( $info_message ); ?></p>
453
+
454
+ <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'backupwordpress' ); ?></span></button>
455
+
456
+ </div>
457
+
458
+ <?php }
459
+
460
  }
461
 
462
  if ( is_multisite() && ! is_main_site() ) {
classes/class-requirements.php CHANGED
@@ -50,7 +50,7 @@ class Requirements {
50
  * @return WP_Error
51
  */
52
  public static function register( $class, $group = 'misc' ) {
53
- self::$requirements[$group][] = $class;
54
  }
55
 
56
  /**
@@ -67,5 +67,4 @@ class Requirements {
67
  return $$class;
68
 
69
  }
70
-
71
  }
50
  * @return WP_Error
51
  */
52
  public static function register( $class, $group = 'misc' ) {
53
+ self::$requirements[ $group ][] = $class;
54
  }
55
 
56
  /**
67
  return $$class;
68
 
69
  }
 
70
  }
classes/class-scheduled-backup.php CHANGED
@@ -38,7 +38,7 @@ class Scheduled_Backup {
38
  'max_backups' => 3,
39
  'excludes' => array(),
40
  'type' => 'complete',
41
- 'reoccurrence' => 'manually'
42
  );
43
 
44
  /**
@@ -76,17 +76,17 @@ class Scheduled_Backup {
76
  sanitize_title( str_ireplace( array(
77
  'http://',
78
  'https://',
79
- 'www'
80
  ), '', home_url() ) ),
81
  $this->get_id(),
82
  $this->get_type(),
83
- current_time( 'Y-m-d-H-i-s' )
84
  ) ) . '.zip';
85
 
86
  $this->database_dump_filename = implode( '-', array(
87
  'database',
88
  sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ),
89
- $this->get_id()
90
  ) ) . '.sql';
91
 
92
  $this->status = new Backup_Status( $this->get_id() );
@@ -212,7 +212,7 @@ class Scheduled_Backup {
212
  /**
213
  * Back compat with old set_status mathod
214
  *
215
- * @deprecated 3.4 Backup->status->set_status()
216
  */
217
  public function set_status( $message ) {
218
  _deprecated_function( __FUNCTION__, '3.4', 'Backup->status->set_status()' );
@@ -253,7 +253,7 @@ class Scheduled_Backup {
253
  * @param $service
254
  * @param array $options
255
  */
256
- public function set_service_options( $service, Array $options ) {
257
  $this->options[ $service ] = $options;
258
  }
259
 
@@ -326,7 +326,6 @@ class Scheduled_Backup {
326
  return;
327
  }
328
 
329
-
330
  $this->options['reoccurrence'] = $reoccurrence;
331
 
332
  if ( 'manually' === $reoccurrence ) {
@@ -575,7 +574,6 @@ class Scheduled_Backup {
575
  if ( pathinfo( $file, PATHINFO_EXTENSION ) === 'zip' && strpos( $file, $this->get_id() ) !== false && ( isset( $this->status ) && $this->get_backup_filename() !== $file ) ) {
576
  $files[ @filemtime( trailingslashit( Path::get_path() ) . $file ) ] = trailingslashit( Path::get_path() ) . $file;
577
  }
578
-
579
  }
580
 
581
  closedir( $handle );
@@ -648,7 +646,7 @@ class Scheduled_Backup {
648
  public function save() {
649
 
650
  // Only save them if they have changed
651
- if ( $this->options !== get_option( 'hmbkp_schedule_' . $this->get_id() ) ) {
652
  update_option( 'hmbkp_schedule_' . $this->get_id(), $this->options );
653
  }
654
 
@@ -676,5 +674,4 @@ class Scheduled_Backup {
676
  }
677
 
678
  }
679
-
680
  }
38
  'max_backups' => 3,
39
  'excludes' => array(),
40
  'type' => 'complete',
41
+ 'reoccurrence' => 'manually',
42
  );
43
 
44
  /**
76
  sanitize_title( str_ireplace( array(
77
  'http://',
78
  'https://',
79
+ 'www',
80
  ), '', home_url() ) ),
81
  $this->get_id(),
82
  $this->get_type(),
83
+ current_time( 'Y-m-d-H-i-s' ),
84
  ) ) . '.zip';
85
 
86
  $this->database_dump_filename = implode( '-', array(
87
  'database',
88
  sanitize_title( str_ireplace( array( 'http://', 'https://', 'www' ), '', home_url() ) ),
89
+ $this->get_id(),
90
  ) ) . '.sql';
91
 
92
  $this->status = new Backup_Status( $this->get_id() );
212
  /**
213
  * Back compat with old set_status mathod
214
  *
215
+ * @deprecated 3.4 Backup->status->set_status()
216
  */
217
  public function set_status( $message ) {
218
  _deprecated_function( __FUNCTION__, '3.4', 'Backup->status->set_status()' );
253
  * @param $service
254
  * @param array $options
255
  */
256
+ public function set_service_options( $service, array $options ) {
257
  $this->options[ $service ] = $options;
258
  }
259
 
326
  return;
327
  }
328
 
 
329
  $this->options['reoccurrence'] = $reoccurrence;
330
 
331
  if ( 'manually' === $reoccurrence ) {
574
  if ( pathinfo( $file, PATHINFO_EXTENSION ) === 'zip' && strpos( $file, $this->get_id() ) !== false && ( isset( $this->status ) && $this->get_backup_filename() !== $file ) ) {
575
  $files[ @filemtime( trailingslashit( Path::get_path() ) . $file ) ] = trailingslashit( Path::get_path() ) . $file;
576
  }
 
577
  }
578
 
579
  closedir( $handle );
646
  public function save() {
647
 
648
  // Only save them if they have changed
649
+ if ( get_option( 'hmbkp_schedule_' . $this->get_id() ) !== $this->options ) {
650
  update_option( 'hmbkp_schedule_' . $this->get_id(), $this->options );
651
  }
652
 
674
  }
675
 
676
  }
 
677
  }
classes/class-schedules.php CHANGED
@@ -86,5 +86,4 @@ class Schedules {
86
  private function instantiate( $id ) {
87
  return new Scheduled_Backup( str_replace( 'hmbkp_schedule_', '', $id ) );
88
  }
89
-
90
  }
86
  private function instantiate( $id ) {
87
  return new Scheduled_Backup( str_replace( 'hmbkp_schedule_', '', $id ) );
88
  }
 
89
  }
classes/class-service.php CHANGED
@@ -186,9 +186,7 @@ abstract class Service {
186
  if ( ! empty( $options ) ) {
187
  return $options;
188
  }
189
-
190
  }
191
-
192
  }
193
 
194
  return array();
@@ -214,5 +212,4 @@ abstract class Service {
214
  public static function intercom_data() {}
215
 
216
  public static function intercom_data_html() {}
217
-
218
  }
186
  if ( ! empty( $options ) ) {
187
  return $options;
188
  }
 
189
  }
 
190
  }
191
 
192
  return array();
212
  public static function intercom_data() {}
213
 
214
  public static function intercom_data_html() {}
 
215
  }
classes/class-services.php CHANGED
@@ -43,8 +43,9 @@ class Services {
43
  */
44
  public static function instance() {
45
 
46
- if ( ! isset( self::$instance ) )
47
  self::$instance = new Services;
 
48
 
49
  return self::$instance;
50
 
@@ -73,7 +74,7 @@ class Services {
73
  *
74
  * @param $filepath
75
  * @param $classname
76
- * @return bool|WP_Error
77
  */
78
  public static function register( $filepath, $classname ) {
79
  if ( ! file_exists( $filepath ) ) {
@@ -88,7 +89,7 @@ class Services {
88
  /**
89
  * De-register an existing service
90
  * @param string $filepath
91
- * @return bool|WP_Error
92
  */
93
  public static function unregister( $filepath ) {
94
 
@@ -122,5 +123,4 @@ class Services {
122
  return $class;
123
 
124
  }
125
-
126
  }
43
  */
44
  public static function instance() {
45
 
46
+ if ( ! isset( self::$instance ) ) {
47
  self::$instance = new Services;
48
+ }
49
 
50
  return self::$instance;
51
 
74
  *
75
  * @param $filepath
76
  * @param $classname
77
+ * @return \WP_Error|boolean
78
  */
79
  public static function register( $filepath, $classname ) {
80
  if ( ! file_exists( $filepath ) ) {
89
  /**
90
  * De-register an existing service
91
  * @param string $filepath
92
+ * @return \WP_Error|boolean
93
  */
94
  public static function unregister( $filepath ) {
95
 
123
  return $class;
124
 
125
  }
 
126
  }
classes/class-setup.php CHANGED
@@ -67,8 +67,6 @@ class HMBKP_Setup {
67
  foreach ( array_map( array( 'self', 'trim_prefix' ), $schedules ) as $item ) {
68
  wp_clear_scheduled_hook( 'hmbkp_schedule_hook', array( 'id' => $item ) );
69
  }
70
-
71
-
72
  }
73
 
74
  public static function trim_prefix( $item ) {
@@ -105,7 +103,7 @@ class HMBKP_Setup {
105
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
106
  }
107
 
108
- deactivate_plugins( dirname( dirname(__FILE__ ) ) . '/backupwordpress.php' );
109
 
110
  if ( isset( $_GET['activate'] ) ) {
111
  unset( $_GET['activate'] );
@@ -177,5 +175,4 @@ class HMBKP_Setup {
177
  '</a>'
178
  );
179
  }
180
-
181
  }
67
  foreach ( array_map( array( 'self', 'trim_prefix' ), $schedules ) as $item ) {
68
  wp_clear_scheduled_hook( 'hmbkp_schedule_hook', array( 'id' => $item ) );
69
  }
 
 
70
  }
71
 
72
  public static function trim_prefix( $item ) {
103
  require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
104
  }
105
 
106
+ deactivate_plugins( dirname( dirname( __FILE__ ) ) . '/backupwordpress.php' );
107
 
108
  if ( isset( $_GET['activate'] ) ) {
109
  unset( $_GET['activate'] );
175
  '</a>'
176
  );
177
  }
 
178
  }
classes/class-webhook-service.php CHANGED
@@ -58,10 +58,10 @@ abstract class Webhook_Service extends Service {
58
 
59
  $subject = sprintf( __( 'Backup of %s Failed', 'backupwordpress' ), $domain );
60
 
61
- $body = array (
62
  'type' => 'backup.error',
63
  'site_url' => site_url(),
64
- 'backup' => array(
65
  'id' => 'backup_' . pathinfo( $file, PATHINFO_FILENAME ),
66
  'start' => '0',
67
  'end' => '0',
@@ -69,14 +69,14 @@ abstract class Webhook_Service extends Service {
69
  'type' => $this->schedule->get_type(),
70
  'status' => array(
71
  'message' => $subject . ' - ' . $error_message,
72
- 'success' => '0'
73
- )
74
- )
75
  );
76
 
77
  } else {
78
 
79
- $body = array (
80
  'type' => 'backup.success',
81
  'site_url' => site_url(),
82
  'backup' => array(
@@ -87,9 +87,9 @@ abstract class Webhook_Service extends Service {
87
  'type' => $this->schedule->get_type(),
88
  'status' => array(
89
  'message' => 'Backup complete',
90
- 'success' => '1'
91
- )
92
- )
93
  );
94
 
95
  }
@@ -105,8 +105,9 @@ abstract class Webhook_Service extends Service {
105
 
106
  }
107
 
108
- public static function intercom_data() { return array(); }
 
 
109
 
110
  public static function intercom_data_html() {}
111
-
112
  }
58
 
59
  $subject = sprintf( __( 'Backup of %s Failed', 'backupwordpress' ), $domain );
60
 
61
+ $body = array(
62
  'type' => 'backup.error',
63
  'site_url' => site_url(),
64
+ 'backup' => array(
65
  'id' => 'backup_' . pathinfo( $file, PATHINFO_FILENAME ),
66
  'start' => '0',
67
  'end' => '0',
69
  'type' => $this->schedule->get_type(),
70
  'status' => array(
71
  'message' => $subject . ' - ' . $error_message,
72
+ 'success' => '0',
73
+ ),
74
+ ),
75
  );
76
 
77
  } else {
78
 
79
+ $body = array(
80
  'type' => 'backup.success',
81
  'site_url' => site_url(),
82
  'backup' => array(
87
  'type' => $this->schedule->get_type(),
88
  'status' => array(
89
  'message' => 'Backup complete',
90
+ 'success' => '1',
91
+ ),
92
+ ),
93
  );
94
 
95
  }
105
 
106
  }
107
 
108
+ public static function intercom_data() {
109
+ return array();
110
+ }
111
 
112
  public static function intercom_data_html() {}
 
113
  }
classes/class-wpremote-webhook-service.php CHANGED
@@ -65,7 +65,6 @@ class WPRemote_Webhook_Service extends Webhook_Service {
65
  protected function get_secret_key() {
66
  return get_option( 'wpr_api_key' );
67
  }
68
-
69
  }
70
 
71
  // Register the service
65
  protected function get_secret_key() {
66
  return get_option( 'wpr_api_key' );
67
  }
 
68
  }
69
 
70
  // Register the service
composer.lock CHANGED
@@ -4,7 +4,7 @@
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
  "This file is @generated automatically"
6
  ],
7
- "hash": "5bc2486184bdd88cfe98a9f29529263c",
8
  "content-hash": "178e95a25ce4467f191024f0a677b2df",
9
  "packages": [
10
  {
@@ -61,16 +61,16 @@
61
  },
62
  {
63
  "name": "symfony/finder",
64
- "version": "v2.8.3",
65
  "source": {
66
  "type": "git",
67
  "url": "https://github.com/symfony/finder.git",
68
- "reference": "877bb4b16ea573cc8c024e9590888fcf7eb7e0f7"
69
  },
70
  "dist": {
71
  "type": "zip",
72
- "url": "https://api.github.com/repos/symfony/finder/zipball/877bb4b16ea573cc8c024e9590888fcf7eb7e0f7",
73
- "reference": "877bb4b16ea573cc8c024e9590888fcf7eb7e0f7",
74
  "shasum": ""
75
  },
76
  "require": {
@@ -106,20 +106,20 @@
106
  ],
107
  "description": "Symfony Finder Component",
108
  "homepage": "https://symfony.com",
109
- "time": "2016-02-22 16:12:45"
110
  },
111
  {
112
  "name": "symfony/process",
113
- "version": "v2.8.3",
114
  "source": {
115
  "type": "git",
116
  "url": "https://github.com/symfony/process.git",
117
- "reference": "7dedd5b60550f33dca16dd7e94ef8aca8b67bbfe"
118
  },
119
  "dist": {
120
  "type": "zip",
121
- "url": "https://api.github.com/repos/symfony/process/zipball/7dedd5b60550f33dca16dd7e94ef8aca8b67bbfe",
122
- "reference": "7dedd5b60550f33dca16dd7e94ef8aca8b67bbfe",
123
  "shasum": ""
124
  },
125
  "require": {
@@ -155,7 +155,7 @@
155
  ],
156
  "description": "Symfony Process Component",
157
  "homepage": "https://symfony.com",
158
- "time": "2016-02-02 13:33:15"
159
  }
160
  ],
161
  "packages-dev": [],
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
  "This file is @generated automatically"
6
  ],
7
+ "hash": "931f56cb09266580e6ee25c07195beed",
8
  "content-hash": "178e95a25ce4467f191024f0a677b2df",
9
  "packages": [
10
  {
61
  },
62
  {
63
  "name": "symfony/finder",
64
+ "version": "v2.8.4",
65
  "source": {
66
  "type": "git",
67
  "url": "https://github.com/symfony/finder.git",
68
+ "reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1"
69
  },
70
  "dist": {
71
  "type": "zip",
72
+ "url": "https://api.github.com/repos/symfony/finder/zipball/ca24cf2cd4e3826f571e0067e535758e73807aa1",
73
+ "reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1",
74
  "shasum": ""
75
  },
76
  "require": {
106
  ],
107
  "description": "Symfony Finder Component",
108
  "homepage": "https://symfony.com",
109
+ "time": "2016-03-10 10:53:53"
110
  },
111
  {
112
  "name": "symfony/process",
113
+ "version": "v2.8.4",
114
  "source": {
115
  "type": "git",
116
  "url": "https://github.com/symfony/process.git",
117
+ "reference": "fb467471952ef5cf8497c029980e556b47545333"
118
  },
119
  "dist": {
120
  "type": "zip",
121
+ "url": "https://api.github.com/repos/symfony/process/zipball/fb467471952ef5cf8497c029980e556b47545333",
122
+ "reference": "fb467471952ef5cf8497c029980e556b47545333",
123
  "shasum": ""
124
  },
125
  "require": {
155
  ],
156
  "description": "Symfony Process Component",
157
  "homepage": "https://symfony.com",
158
+ "time": "2016-03-23 13:11:46"
159
  }
160
  ],
161
  "packages-dev": [],
functions/core.php CHANGED
@@ -33,7 +33,7 @@ function update() {
33
  'bkpwp_calculation',
34
  'bkpwppath',
35
  'bkpwp_status_config',
36
- 'bkpwp_status'
37
  );
38
 
39
  foreach ( $legacy_options as $option ) {
@@ -60,13 +60,9 @@ function update() {
60
  // Backup type
61
  if ( ( defined( 'HMBKP_FILES_ONLY' ) && HMBKP_FILES_ONLY ) || get_option( 'hmbkp_files_only' ) ) {
62
  $legacy_schedule->set_type( 'file' );
63
- }
64
-
65
- elseif ( ( defined( 'HMBKP_DATABASE_ONLY' ) && HMBKP_DATABASE_ONLY ) || get_option( 'hmbkp_database_only' ) ) {
66
  $legacy_schedule->set_type( 'database' );
67
- }
68
-
69
- else {
70
  $legacy_schedule->set_type( 'complete' );
71
  }
72
 
@@ -86,9 +82,7 @@ function update() {
86
  // Max backups
87
  if ( defined( 'HMBKP_MAX_BACKUPS' ) && is_numeric( HMBKP_MAX_BACKUPS ) ) {
88
  $legacy_schedule->set_max_backups( (int) HMBKP_MAX_BACKUPS );
89
- }
90
-
91
- else {
92
  $legacy_schedule->set_max_backups( (int) get_option( 'hmbkp_max_backups', 10 ) );
93
  }
94
 
@@ -100,9 +94,7 @@ function update() {
100
  // Backup email
101
  if ( defined( 'HMBKP_EMAIL' ) && is_email( HMBKP_EMAIL ) ) {
102
  $legacy_schedule->set_service_options( 'HMBKP_Email_Service', array( 'email' => HMBKP_EMAIL ) );
103
- }
104
-
105
- elseif ( is_email( get_option( 'hmbkp_email_address' ) ) ) {
106
  $legacy_schedule->set_service_options( 'HMBKP_Email_Service', array( 'email' => get_option( 'hmbkp_email_address' ) ) );
107
  }
108
 
@@ -133,7 +125,6 @@ function update() {
133
  foreach ( array( 'hmbkp_database_only', 'hmbkp_files_only', 'hmbkp_max_backups', 'hmbkp_email_address', 'hmbkp_email', 'hmbkp_schedule_frequency', 'hmbkp_disable_automatic_backup' ) as $option_name ) {
134
  delete_option( $option_name );
135
  }
136
-
137
  }
138
 
139
  // Update from 2.x to 3.0
@@ -203,8 +194,6 @@ function update() {
203
  update_option( $schedule_id, $schedule_settings );
204
  }
205
  }
206
-
207
-
208
  }
209
 
210
  // Update to 3.1.5
@@ -271,14 +260,13 @@ function update() {
271
 
272
  $reoccurrence = $schedule->get_reoccurrence();
273
 
274
- if ( $reoccurrence !== 'manually' && strpos( $reoccurrence, 'hmbkp_' ) === 0 ) {
275
  $schedule->set_reoccurrence( substr( $reoccurrence, 6 ) );
276
  }
277
 
278
  $schedule->save();
279
 
280
  }
281
-
282
  }
283
 
284
  // Update from 3.3.4
@@ -383,11 +371,11 @@ function rmdirtree( $dir ) {
383
  return new WP_Error( 'hmbkp_invalid_action_error', sprintf( __( 'You can only delete directories inside your WordPress installation', 'backupwordpress' ) ) );
384
  }
385
 
386
- if ( is_file( $dir ) ){
387
  @unlink( $dir );
388
  }
389
 
390
- if ( ! is_dir( $dir ) || ! is_readable( $dir ) ){
391
  return false;
392
  }
393
 
@@ -395,14 +383,11 @@ function rmdirtree( $dir ) {
395
 
396
  foreach ( $files as $file ) {
397
 
398
- if ( $file->isDir() ){
399
  @rmdir( $file->getPathname() );
400
- }
401
-
402
- else{
403
  @unlink( $file->getPathname() );
404
  }
405
-
406
  }
407
 
408
  @rmdir( $dir );
@@ -426,6 +411,18 @@ function is_backup_possible() {
426
  return false;
427
  }
428
 
 
 
 
 
 
 
 
 
 
 
 
 
429
  return true;
430
  }
431
 
@@ -440,8 +437,9 @@ function get_max_attachment_size() {
440
 
441
  $max_size = '10mb';
442
 
443
- if ( defined( 'HMBKP_ATTACHMENT_MAX_FILESIZE' ) && wp_convert_hr_to_bytes( HMBKP_ATTACHMENT_MAX_FILESIZE ) )
444
  $max_size = HMBKP_ATTACHMENT_MAX_FILESIZE;
 
445
 
446
  return wp_convert_hr_to_bytes( $max_size );
447
 
@@ -499,7 +497,7 @@ function determine_start_time( $type, $times = array() ) {
499
  'hours' => date( 'G', $default_timestamp ),
500
  'day_of_week' => date( 'l', $default_timestamp ),
501
  'day_of_month' => date( 'j', $default_timestamp ),
502
- 'now' => time()
503
  );
504
 
505
  $args = wp_parse_args( $times, $default_times );
@@ -509,10 +507,7 @@ function determine_start_time( $type, $times = array() ) {
509
  // Allow the hours and minutes to be overwritten by a constant
510
  if ( defined( 'HMBKP_SCHEDULE_TIME' ) && HMBKP_SCHEDULE_TIME ) {
511
  $hm = HMBKP_SCHEDULE_TIME;
512
- }
513
-
514
- // The hour and minute that the schedule should start on
515
- else {
516
  $hm = $args['hours'] . ':' . $args['minutes'] . ':00';
517
  }
518
 
@@ -646,15 +641,10 @@ function list_directory_by_total_filesize( $directory, Excludes $excludes ) {
646
  $files_with_size[ $filesize ] = $entry;
647
 
648
  } elseif ( 0 === $filesize ) {
649
-
650
  $empty_files[] = $entry;
651
-
652
  } else {
653
-
654
  $files_with_no_size[] = $entry;
655
-
656
  }
657
-
658
  }
659
 
660
  // Sort files by filesize, largest first
33
  'bkpwp_calculation',
34
  'bkpwppath',
35
  'bkpwp_status_config',
36
+ 'bkpwp_status',
37
  );
38
 
39
  foreach ( $legacy_options as $option ) {
60
  // Backup type
61
  if ( ( defined( 'HMBKP_FILES_ONLY' ) && HMBKP_FILES_ONLY ) || get_option( 'hmbkp_files_only' ) ) {
62
  $legacy_schedule->set_type( 'file' );
63
+ } elseif ( ( defined( 'HMBKP_DATABASE_ONLY' ) && HMBKP_DATABASE_ONLY ) || get_option( 'hmbkp_database_only' ) ) {
 
 
64
  $legacy_schedule->set_type( 'database' );
65
+ } else {
 
 
66
  $legacy_schedule->set_type( 'complete' );
67
  }
68
 
82
  // Max backups
83
  if ( defined( 'HMBKP_MAX_BACKUPS' ) && is_numeric( HMBKP_MAX_BACKUPS ) ) {
84
  $legacy_schedule->set_max_backups( (int) HMBKP_MAX_BACKUPS );
85
+ } else {
 
 
86
  $legacy_schedule->set_max_backups( (int) get_option( 'hmbkp_max_backups', 10 ) );
87
  }
88
 
94
  // Backup email
95
  if ( defined( 'HMBKP_EMAIL' ) && is_email( HMBKP_EMAIL ) ) {
96
  $legacy_schedule->set_service_options( 'HMBKP_Email_Service', array( 'email' => HMBKP_EMAIL ) );
97
+ } elseif ( is_email( get_option( 'hmbkp_email_address' ) ) ) {
 
 
98
  $legacy_schedule->set_service_options( 'HMBKP_Email_Service', array( 'email' => get_option( 'hmbkp_email_address' ) ) );
99
  }
100
 
125
  foreach ( array( 'hmbkp_database_only', 'hmbkp_files_only', 'hmbkp_max_backups', 'hmbkp_email_address', 'hmbkp_email', 'hmbkp_schedule_frequency', 'hmbkp_disable_automatic_backup' ) as $option_name ) {
126
  delete_option( $option_name );
127
  }
 
128
  }
129
 
130
  // Update from 2.x to 3.0
194
  update_option( $schedule_id, $schedule_settings );
195
  }
196
  }
 
 
197
  }
198
 
199
  // Update to 3.1.5
260
 
261
  $reoccurrence = $schedule->get_reoccurrence();
262
 
263
+ if ( 'manually' !== $reoccurrence && strpos( $reoccurrence, 'hmbkp_' ) === 0 ) {
264
  $schedule->set_reoccurrence( substr( $reoccurrence, 6 ) );
265
  }
266
 
267
  $schedule->save();
268
 
269
  }
 
270
  }
271
 
272
  // Update from 3.3.4
371
  return new WP_Error( 'hmbkp_invalid_action_error', sprintf( __( 'You can only delete directories inside your WordPress installation', 'backupwordpress' ) ) );
372
  }
373
 
374
+ if ( is_file( $dir ) ) {
375
  @unlink( $dir );
376
  }
377
 
378
+ if ( ! is_dir( $dir ) || ! is_readable( $dir ) ) {
379
  return false;
380
  }
381
 
383
 
384
  foreach ( $files as $file ) {
385
 
386
+ if ( $file->isDir() ) {
387
  @rmdir( $file->getPathname() );
388
+ } else {
 
 
389
  @unlink( $file->getPathname() );
390
  }
 
391
  }
392
 
393
  @rmdir( $dir );
411
  return false;
412
  }
413
 
414
+ if ( disk_space_low() ) {
415
+ return false;
416
+ }
417
+
418
+ if ( ! Requirement_Mysqldump_Command_Path::test() && ! Requirement_PDO::test() ) {
419
+ return false;
420
+ }
421
+
422
+ if ( ! Requirement_Zip_Command_Path::test() && ! Requirement_Zip_Archive::test() ) {
423
+ return false;
424
+ }
425
+
426
  return true;
427
  }
428
 
437
 
438
  $max_size = '10mb';
439
 
440
+ if ( defined( 'HMBKP_ATTACHMENT_MAX_FILESIZE' ) && wp_convert_hr_to_bytes( HMBKP_ATTACHMENT_MAX_FILESIZE ) ) {
441
  $max_size = HMBKP_ATTACHMENT_MAX_FILESIZE;
442
+ }
443
 
444
  return wp_convert_hr_to_bytes( $max_size );
445
 
497
  'hours' => date( 'G', $default_timestamp ),
498
  'day_of_week' => date( 'l', $default_timestamp ),
499
  'day_of_month' => date( 'j', $default_timestamp ),
500
+ 'now' => time(),
501
  );
502
 
503
  $args = wp_parse_args( $times, $default_times );
507
  // Allow the hours and minutes to be overwritten by a constant
508
  if ( defined( 'HMBKP_SCHEDULE_TIME' ) && HMBKP_SCHEDULE_TIME ) {
509
  $hm = HMBKP_SCHEDULE_TIME;
510
+ } else { // The hour and minute that the schedule should start on
 
 
 
511
  $hm = $args['hours'] . ':' . $args['minutes'] . ':00';
512
  }
513
 
641
  $files_with_size[ $filesize ] = $entry;
642
 
643
  } elseif ( 0 === $filesize ) {
 
644
  $empty_files[] = $entry;
 
645
  } else {
 
646
  $files_with_no_size[] = $entry;
 
647
  }
 
648
  }
649
 
650
  // Sort files by filesize, largest first
functions/interface.php CHANGED
@@ -85,15 +85,13 @@ function admin_notices() {
85
 
86
  </ul>
87
 
88
- <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'backupwordpress' ); ?></span></button>
89
-
90
  </div>
91
 
92
  <?php endif; ?>
93
 
94
  <?php if ( ! empty( $notices['server_config'] ) ) : ?>
95
 
96
- <div id="hmbkp-warning-server" class="error notice is-dismissible">
97
 
98
  <ul>
99
 
@@ -105,8 +103,6 @@ function admin_notices() {
105
 
106
  </ul>
107
 
108
- <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'backupwordpress' ); ?></span></button>
109
-
110
  </div>
111
 
112
  <?php endif; ?>
@@ -127,8 +123,6 @@ function admin_notices() {
127
 
128
  <?php endforeach; ?>
129
 
130
- <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'backupwordpress' ); ?></span></button>
131
-
132
  </div>
133
 
134
  <?php endif; ?>
@@ -188,7 +182,15 @@ function set_server_config_notices() {
188
  }
189
 
190
  if ( ! Requirement_Mysqldump_Command_Path::test() && ! Requirement_PDO::test() ) {
191
- $messages[] = sprintf( __( 'Your database cannot be backed up because your server doesn\'t support %1$s or %2$s. Please contact your host and ask them to enable them.', 'backupwordpress' ), '<code>mysqldump</code>', '<code>PDO</code>' );
 
 
 
 
 
 
 
 
192
  }
193
 
194
  if ( count( $messages ) > 0 ) {
@@ -323,9 +325,9 @@ function translated_schedule_title( $slug, $title ) {
323
 
324
  }
325
 
326
- function get_settings_url() {
327
 
328
- $url = is_multisite() ? network_admin_url( 'settings.php?page=' . HMBKP_PLUGIN_SLUG ) : admin_url( 'tools.php?page=' . HMBKP_PLUGIN_SLUG );
329
 
330
  schedules::get_instance()->refresh_schedules();
331
 
@@ -432,3 +434,28 @@ function is_same_size_format( $size, $other_size ) {
432
 
433
  return preg_replace( '/[0-9]+/', '', size_format( $size ) ) === preg_replace( '/[0-9]+/', '', size_format( $other_size ) );
434
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  </ul>
87
 
 
 
88
  </div>
89
 
90
  <?php endif; ?>
91
 
92
  <?php if ( ! empty( $notices['server_config'] ) ) : ?>
93
 
94
+ <div id="hmbkp-warning-server" class="error notice">
95
 
96
  <ul>
97
 
103
 
104
  </ul>
105
 
 
 
106
  </div>
107
 
108
  <?php endif; ?>
123
 
124
  <?php endforeach; ?>
125
 
 
 
126
  </div>
127
 
128
  <?php endif; ?>
182
  }
183
 
184
  if ( ! Requirement_Mysqldump_Command_Path::test() && ! Requirement_PDO::test() ) {
185
+ $messages[] = sprintf( __( 'Your site cannot be backed up because your server doesn\'t support %1$s or %2$s. Please contact your host and ask them to enable them.', 'backupwordpress' ), '<code>mysqldump</code>', '<code>PDO::mysql</code>' );
186
+ }
187
+
188
+ if ( ! Requirement_Zip_Command_Path::test() && ! Requirement_Zip_Archive::test() ) {
189
+ $messages[] = sprintf( __( 'Your site cannot be backed up because your server doesn\'t support %1$s or %2$s. Please contact your host and ask them to enable them.', 'backupwordpress' ), '<code>zip</code>', '<code>ZipArchive</code>' );
190
+ }
191
+
192
+ if ( disk_space_low() ) {
193
+ $messages[] = sprintf( __( 'Your server only has %s of disk space left which probably isn\'t enough to complete a backup. Try deleting some existing backups or other files to free up space.', 'backupwordpress' ), '<code>' . size_format( disk_free_space( Path::get_path() ) ) . '</code>' );
194
  }
195
 
196
  if ( count( $messages ) > 0 ) {
325
 
326
  }
327
 
328
+ function get_settings_url( $slug = HMBKP_PLUGIN_SLUG ) {
329
 
330
+ $url = is_multisite() ? network_admin_url( 'settings.php?page=' . $slug ) : admin_url( 'tools.php?page=' . $slug );
331
 
332
  schedules::get_instance()->refresh_schedules();
333
 
434
 
435
  return preg_replace( '/[0-9]+/', '', size_format( $size ) ) === preg_replace( '/[0-9]+/', '', size_format( $other_size ) );
436
  }
437
+
438
+ /**
439
+ * Check whether the server is low on disk space.
440
+ *
441
+ * @return bool Whether there's less disk space less than 2 * the entire size of the site.
442
+ */
443
+ function disk_space_low( $backup_size = false ) {
444
+
445
+ if ( ! $backup_size ) {
446
+
447
+ $site_size = new Site_Size();
448
+
449
+ if ( $site_size->is_site_size_cached() ) {
450
+ return false;
451
+ }
452
+
453
+ $backup_size = $site_size->get_site_size() * 2;
454
+
455
+ }
456
+
457
+ $disk_space = disk_free_space( Path::get_path() );
458
+
459
+ return $backup_size >= $disk_space;
460
+
461
+ }
languages/backupwordpress.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the GPL-2+.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: BackUpWordPress 3.5-beta\n"
6
  "Report-Msgid-Bugs-To: backupwordpress@hmn.md\n"
7
- "POT-Creation-Date: 2016-03-10 17:03:08+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -13,66 +13,72 @@ msgstr ""
13
  "Language-Team: Human Made Limited\n"
14
  "X-Generator: grunt-wp-i18n 0.5.4\n"
15
 
16
- #: admin/actions.php:180
17
  msgid "The schedule ID was not provided. Aborting."
18
  msgstr ""
19
 
20
- #: admin/actions.php:236
21
  msgid "Backup type cannot be empty"
22
  msgstr ""
23
 
24
- #: admin/actions.php:240
25
  msgid "Invalid backup type"
26
  msgstr ""
27
 
28
- #: admin/actions.php:254
29
  msgid "Schedule cannot be empty"
30
  msgstr ""
31
 
32
- #: admin/actions.php:258
33
  msgid "Invalid schedule"
34
  msgstr ""
35
 
36
- #: admin/actions.php:272
37
  msgid "Day of the week must be a valid, lowercase day name"
38
  msgstr ""
39
 
40
- #: admin/actions.php:291
41
  msgid "Day of month must be between 1 and 31"
42
  msgstr ""
43
 
44
- #: admin/actions.php:310
45
  msgid "Hours must be between 0 and 23"
46
  msgstr ""
47
 
48
- #: admin/actions.php:329
49
  msgid "Minutes must be between 0 and 59"
50
  msgstr ""
51
 
52
- #: admin/actions.php:343
53
  msgid "Max backups can't be empty"
54
  msgstr ""
55
 
56
- #: admin/actions.php:347
57
  msgid "Max backups must be a number"
58
  msgstr ""
59
 
60
- #: admin/actions.php:351
61
  msgid "Max backups must be greater than 0"
62
  msgstr ""
63
 
64
- #: admin/actions.php:695 admin/actions.php:701
 
 
 
 
 
 
65
  msgid "BackUpWordPress has detected a problem."
66
  msgstr ""
67
 
68
- #: admin/actions.php:695
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. "
72
  "See the %3$s for more details."
73
  msgstr ""
74
 
75
- #: admin/actions.php:701
76
  msgid ""
77
  "%1$s is returning a %2$s response which could mean cron jobs aren't getting "
78
  "fired properly. BackUpWordPress relies on wp-cron to run scheduled backups, "
@@ -106,7 +112,7 @@ msgid ""
106
  "settings. %4$s. Defined %5$s will be highlighted."
107
  msgstr ""
108
 
109
- #: admin/constants.php:9 admin/menu.php:80
110
  msgid "Constants"
111
  msgstr ""
112
 
@@ -116,7 +122,7 @@ msgstr ""
116
 
117
  #: admin/constants.php:20 admin/constants.php:36 admin/constants.php:52
118
  #: admin/constants.php:68 admin/constants.php:84 admin/constants.php:100
119
- #: admin/constants.php:116 classes/class-email-service.php:60
120
  msgid "You've set it to: %s"
121
  msgstr ""
122
 
@@ -128,7 +134,7 @@ msgstr ""
128
 
129
  #: admin/constants.php:23 admin/constants.php:39 admin/constants.php:55
130
  #: admin/constants.php:71 admin/constants.php:87 admin/constants.php:103
131
- #: admin/constants.php:119 classes/class-email-service.php:63
132
  msgid "e.g."
133
  msgstr ""
134
 
@@ -193,6 +199,68 @@ msgstr ""
193
  msgid "Yes, I want to enable support"
194
  msgstr ""
195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  #: admin/faq.php:2
197
  msgid "Where does BackUpWordPress store the backup files?"
198
  msgstr ""
@@ -366,43 +434,51 @@ msgid ""
366
  "emailing backupwordpress@hmn.md"
367
  msgstr ""
368
 
369
- #: admin/menu.php:14 admin/menu.php:16
370
- msgid "Manage Backups"
371
  msgstr ""
372
 
373
- #: admin/menu.php:14 admin/menu.php:16 admin/menu.php:44
374
  msgid "Backups"
375
  msgstr ""
376
 
377
- #: admin/menu.php:75
 
 
 
 
 
 
 
 
378
  msgid "FAQ"
379
  msgstr ""
380
 
381
- #: admin/menu.php:93
382
  msgid "Server Info"
383
  msgstr ""
384
 
385
- #: admin/menu.php:100
386
  msgid "For more information:"
387
  msgstr ""
388
 
389
- #: admin/menu.php:100
390
  msgid "Support Forums"
391
  msgstr ""
392
 
393
- #: admin/menu.php:100
394
  msgid "Help with translation"
395
  msgstr ""
396
 
397
- #: admin/page.php:13
398
  msgid "Support"
399
  msgstr ""
400
 
401
- #: admin/page.php:16
402
  msgid "Enable Support"
403
  msgstr ""
404
 
405
- #: admin/page.php:25
406
  msgid ""
407
  "If you're finding BackUpWordPress useful, please %1$s rate it on the plugin "
408
  "directory%2$s."
@@ -457,7 +533,7 @@ msgstr ""
457
  msgid "Status"
458
  msgstr ""
459
 
460
- #: admin/schedule-form-excludes.php:162 admin/schedule-form-excludes.php:267
461
  msgid "%s of %s"
462
  msgstr ""
463
 
@@ -465,40 +541,40 @@ msgstr ""
465
  msgid "Refresh"
466
  msgstr ""
467
 
468
- #: admin/schedule-form-excludes.php:177 admin/schedule-form-excludes.php:299
469
  msgid "Symlink"
470
  msgstr ""
471
 
472
- #: admin/schedule-form-excludes.php:179 admin/schedule-form-excludes.php:302
473
  msgid "Folder"
474
  msgstr ""
475
 
476
- #: admin/schedule-form-excludes.php:304
477
  msgid "File"
478
  msgstr ""
479
 
480
- #: admin/schedule-form-excludes.php:313
481
  msgid "Unreadable files won't be backed up."
482
  msgstr ""
483
 
484
- #: admin/schedule-form-excludes.php:313
485
  msgid "Unreadable"
486
  msgstr ""
487
 
488
- #: admin/schedule-form-excludes.php:317
489
  msgid "Excluded"
490
  msgstr ""
491
 
492
- #: admin/schedule-form-excludes.php:333
493
  msgid "Exclude &rarr;"
494
  msgstr ""
495
 
496
- #: admin/schedule-form-excludes.php:346
497
  msgid "This folder is empty"
498
  msgstr ""
499
 
500
- #: admin/schedule-form-excludes.php:357 admin/schedule-form.php:204
501
- #: admin/schedule-settings.php:90
502
  msgid "Done"
503
  msgstr ""
504
 
@@ -650,19 +726,19 @@ msgstr ""
650
  msgid "store the last %1$s backups in %2$s"
651
  msgstr ""
652
 
653
- #: admin/schedule-sentence.php:132
654
  msgid "Send a copy of each backup to %s."
655
  msgstr ""
656
 
657
- #: admin/schedule-sentence.php:165
658
  msgid "Backups will be compressed and should be smaller than this."
659
  msgstr ""
660
 
661
- #: admin/schedule-sentence.php:169
662
  msgid "this shouldn't take long&hellip;"
663
  msgstr ""
664
 
665
- #: admin/schedule-sentence.php:169
666
  msgid "calculating the size of your site&hellip;"
667
  msgstr ""
668
 
@@ -674,18 +750,12 @@ msgstr ""
674
  msgid "Excludes"
675
  msgstr ""
676
 
677
- #: admin/schedule-settings.php:29 functions/interface.php:36
678
  msgid "Delete"
679
  msgstr ""
680
 
681
- #: admin/upsell.php:3
682
- msgid "Backup to"
683
- msgstr ""
684
-
685
- #: admin/upsell.php:18
686
- msgid ""
687
- "%1$sor buy the %2$sDeveloper Bundle%3$s now for only &dollar;99 (all "
688
- "Destinations &amp; Unlimited Sites)%4$s"
689
  msgstr ""
690
 
691
  #: classes/backup/class-backup.php:57
@@ -720,166 +790,178 @@ msgstr ""
720
  msgid "Backup Failed"
721
  msgstr ""
722
 
723
- #: classes/class-email-service.php:28
724
  msgid "Email notification"
725
  msgstr ""
726
 
727
- #: classes/class-email-service.php:34
728
  msgid ""
729
  "Receive a notification email when a backup completes. If the backup is "
730
  "small enough (&lt; %s), then it will be attached to the email. Separate "
731
  "multiple email addresses with a comma."
732
  msgstr ""
733
 
734
- #: classes/class-email-service.php:63
735
  msgid ""
736
  "The maximum filesize of your backup that will be attached to your "
737
  "notification emails . Defaults to %s."
738
  msgstr ""
739
 
740
- #: classes/class-email-service.php:82
741
  msgid "Send an email notification to %s"
742
  msgstr ""
743
 
744
- #: classes/class-email-service.php:117
745
  msgid "%s isn't a valid email"
746
  msgstr ""
747
 
748
- #: classes/class-email-service.php:179 classes/class-webhook-service.php:59
749
  msgid "Backup of %s Failed"
750
  msgstr ""
751
 
752
- #: classes/class-email-service.php:181
753
  msgid "BackUpWordPress was unable to backup your site %1$s."
754
  msgstr ""
755
 
756
- #: classes/class-email-service.php:181
757
  msgid "Here are the errors that we've encountered:"
758
  msgstr ""
759
 
760
- #: classes/class-email-service.php:181
761
  msgid ""
762
  "If the errors above look like Martian, forward this email to %3$s and we'll "
763
  "take a look"
764
  msgstr ""
765
 
766
- #: classes/class-email-service.php:181
767
  msgid ""
768
  "Kind Regards,\n"
769
  "The Apologetic BackUpWordPress Backup Emailing Robot"
770
  msgstr ""
771
 
772
- #: classes/class-email-service.php:189
773
  msgid "Backup of %s"
774
  msgstr ""
775
 
776
- #: classes/class-email-service.php:194 classes/class-email-service.php:203
777
  msgid "BackUpWordPress has completed a backup of your site %1$s."
778
  msgstr ""
779
 
780
- #: classes/class-email-service.php:194
781
  msgid "The backup file should be attached to this email."
782
  msgstr ""
783
 
784
- #: classes/class-email-service.php:194 classes/class-email-service.php:203
785
  msgid "You can download the backup file by clicking the link below:"
786
  msgstr ""
787
 
788
- #: classes/class-email-service.php:194 classes/class-email-service.php:203
789
  msgid ""
790
  "Kind Regards,\n"
791
  "The Happy BackUpWordPress Backup Emailing Robot"
792
  msgstr ""
793
 
794
- #: classes/class-email-service.php:203
795
  msgid "Unfortunately, the backup file was too large to attach to this email."
796
  msgstr ""
797
 
798
- #: classes/class-path.php:342
799
  msgid "This %s file ensures that other people cannot download your backup files."
800
  msgstr ""
801
 
802
- #: classes/class-plugin.php:230
803
  msgid "Update"
804
  msgstr ""
805
 
806
- #: classes/class-plugin.php:231
807
  msgid "Cancel"
808
  msgstr ""
809
 
810
- #: classes/class-plugin.php:232
811
  msgid ""
812
  "Are you sure you want to delete this schedule? All of its backups will also "
813
  "be deleted."
814
  msgstr ""
815
 
816
- #: classes/class-plugin.php:232 classes/class-plugin.php:233
817
- #: classes/class-plugin.php:234 classes/class-plugin.php:235
818
  msgid "'Cancel' to go back, 'OK' to delete."
819
  msgstr ""
820
 
821
- #: classes/class-plugin.php:233
822
  msgid "Are you sure you want to delete this backup?"
823
  msgstr ""
824
 
825
- #: classes/class-plugin.php:234
826
  msgid "Are you sure you want to remove this exclude rule?"
827
  msgstr ""
828
 
829
- #: classes/class-plugin.php:235
830
  msgid ""
831
  "Reducing the number of backups that are stored on this server will cause "
832
  "some of your existing backups to be deleted. Are you sure that's what you "
833
  "want?"
834
  msgstr ""
835
 
 
 
 
 
 
 
 
 
 
 
 
 
836
  #: classes/class-scheduled-backup.php:321
837
  msgid "Argument 1 for %s must be a valid cron recurrence or \"manually\""
838
  msgstr ""
839
 
840
- #: classes/class-scheduled-backup.php:428 functions/interface.php:265
841
  msgid "Starting backup..."
842
  msgstr ""
843
 
844
- #: classes/class-scheduled-backup.php:430
845
- #: classes/class-scheduled-backup.php:445
846
  msgid "Deleting old backups..."
847
  msgstr ""
848
 
849
- #: classes/class-scheduled-backup.php:545
850
  #. translators: min=minute
851
  msgid "%s min"
852
  msgid_plural "%s mins"
853
  msgstr[0] ""
854
  msgstr[1] ""
855
 
856
- #: classes/class-scheduled-backup.php:555
857
  msgid "%s hour"
858
  msgid_plural "%s hours"
859
  msgstr[0] ""
860
  msgstr[1] ""
861
 
862
- #: classes/class-scheduled-backup.php:617
863
  msgid "Argument 1 for %s must be a non-empty string"
864
  msgstr ""
865
 
866
- #: classes/class-scheduled-backup.php:622
867
  msgid "%s doesn't exist"
868
  msgstr ""
869
 
870
- #: classes/class-scheduled-backup.php:627
871
  msgid "That backup wasn't created by this schedule"
872
  msgstr ""
873
 
874
- #: classes/class-services.php:80
875
  msgid "Argument 1 for %s must be a valid filepath"
876
  msgstr ""
877
 
878
- #: classes/class-services.php:96
879
  msgid "Argument 1 for %s must be a registered service"
880
  msgstr ""
881
 
882
- #: classes/class-services.php:114 classes/deprecated.php:81
883
  msgid "Argument 1 for %s must be a valid class"
884
  msgstr ""
885
 
@@ -887,7 +969,7 @@ msgstr ""
887
  msgid "BackUpWordPress"
888
  msgstr ""
889
 
890
- #: classes/class-setup.php:171
891
  msgid ""
892
  "BackUpWordPress requires PHP version %1$s or later and WordPress version "
893
  "%2$s or later to run. It has not been activated. %3$s%4$s%5$sLearn more%6$s"
@@ -897,41 +979,41 @@ msgstr ""
897
  msgid "Error: %s"
898
  msgstr ""
899
 
900
- #: functions/core.php:343
901
  msgid "BackUpWordPress has set up your default schedules."
902
  msgstr ""
903
 
904
- #: functions/core.php:343
905
  msgid ""
906
  "By default BackUpWordPress performs a daily backup of your database and a "
907
  "weekly backup of your database &amp; files. You can modify these schedules."
908
  msgstr ""
909
 
910
- #: functions/core.php:359
911
  msgid "Once Hourly"
912
  msgstr ""
913
 
914
- #: functions/core.php:360
915
  msgid "Twice Daily"
916
  msgstr ""
917
 
918
- #: functions/core.php:361
919
  msgid "Once Daily"
920
  msgstr ""
921
 
922
- #: functions/core.php:362
923
  msgid "Once Weekly"
924
  msgstr ""
925
 
926
- #: functions/core.php:363
927
  msgid "Once Every Two Weeks"
928
  msgstr ""
929
 
930
- #: functions/core.php:364
931
  msgid "Once Monthly"
932
  msgstr ""
933
 
934
- #: functions/core.php:383
935
  msgid "You can only delete directories inside your WordPress installation"
936
  msgstr ""
937
 
@@ -943,176 +1025,178 @@ msgstr ""
943
  msgid "BackUpWordPress detected issues with your last backup."
944
  msgstr ""
945
 
946
- #: functions/interface.php:88 functions/interface.php:108
947
- #: functions/interface.php:130
948
- msgid "Dismiss this notice."
949
- msgstr ""
950
-
951
- #: functions/interface.php:153
952
  msgid ""
953
  "The backups directory can't be created because your %s directory isn't "
954
  "writable. Please create the folder manually."
955
  msgstr ""
956
 
957
- #: functions/interface.php:157
958
  msgid "The backups directory isn't writable. Please fix the permissions."
959
  msgstr ""
960
 
961
- #: functions/interface.php:161
962
  msgid ""
963
  "%1$s is running in %2$s, please contact your host and ask them to disable "
964
  "it. BackUpWordPress may not work correctly whilst %3$s is on."
965
  msgstr ""
966
 
967
- #: functions/interface.php:161
968
  msgid "http://php.net/manual/en/features.safe-mode.php"
969
  msgstr ""
970
 
971
- #: functions/interface.php:161
972
  msgid "Safe Mode"
973
  msgstr ""
974
 
975
- #: functions/interface.php:168
976
  msgid ""
977
  "Your server has an %1$s restriction in effect and your custom backups "
978
  "directory (%2$s) is not within the allowed path(s): (%3$s)."
979
  msgstr ""
980
 
981
- #: functions/interface.php:171
982
  msgid "Your custom path does not exist"
983
  msgstr ""
984
 
985
- #: functions/interface.php:176
986
  msgid ""
987
  "Your custom backups directory %1$s doesn't exist and can't be created, your "
988
  "backups will be saved to %2$s instead."
989
  msgstr ""
990
 
991
- #: functions/interface.php:180
992
  msgid ""
993
  "Your custom backups directory %1$s isn't writable, new backups will be "
994
  "saved to %2$s instead."
995
  msgstr ""
996
 
997
- #: functions/interface.php:187
998
  msgid "Your site root path %s isn't readable."
999
  msgstr ""
1000
 
1001
- #: functions/interface.php:191
 
 
 
 
 
 
1002
  msgid ""
1003
- "Your database cannot be backed up because your server doesn't support %1$s "
1004
- "or %2$s. Please contact your host and ask them to enable them."
 
1005
  msgstr ""
1006
 
1007
- #: functions/interface.php:232
1008
  msgid "Database and Files"
1009
  msgstr ""
1010
 
1011
- #: functions/interface.php:236
1012
  msgid "Files"
1013
  msgstr ""
1014
 
1015
- #: functions/interface.php:240
1016
  msgid "Database"
1017
  msgstr ""
1018
 
1019
- #: functions/interface.php:247
1020
  msgid "Legacy"
1021
  msgstr ""
1022
 
1023
- #: functions/interface.php:264
1024
  msgid "Started %s ago"
1025
  msgstr ""
1026
 
1027
- #: functions/interface.php:266
1028
  msgid "cancel"
1029
  msgstr ""
1030
 
1031
- #: functions/interface.php:284
1032
  msgid "No backups completed"
1033
  msgstr ""
1034
 
1035
- #: functions/interface.php:295
1036
  msgid "Complete Hourly"
1037
  msgstr ""
1038
 
1039
- #: functions/interface.php:296
1040
  msgid "File Hourly"
1041
  msgstr ""
1042
 
1043
- #: functions/interface.php:297
1044
  msgid "Database Hourly"
1045
  msgstr ""
1046
 
1047
- #: functions/interface.php:298
1048
  msgid "Complete Twice Daily"
1049
  msgstr ""
1050
 
1051
- #: functions/interface.php:299
1052
  msgid "File Twice Daily"
1053
  msgstr ""
1054
 
1055
- #: functions/interface.php:300
1056
  msgid "Database Twice Daily"
1057
  msgstr ""
1058
 
1059
- #: functions/interface.php:301
1060
  msgid "Complete Daily"
1061
  msgstr ""
1062
 
1063
- #: functions/interface.php:302
1064
  msgid "File Daily"
1065
  msgstr ""
1066
 
1067
- #: functions/interface.php:303
1068
  msgid "Database Daily"
1069
  msgstr ""
1070
 
1071
- #: functions/interface.php:304
1072
  msgid "Complete Weekly"
1073
  msgstr ""
1074
 
1075
- #: functions/interface.php:305
1076
  msgid "File Weekly"
1077
  msgstr ""
1078
 
1079
- #: functions/interface.php:306
1080
  msgid "Database Weekly"
1081
  msgstr ""
1082
 
1083
- #: functions/interface.php:307
1084
  msgid "Complete Every Two Weeks"
1085
  msgstr ""
1086
 
1087
- #: functions/interface.php:308
1088
  msgid "File Every Two Weeks"
1089
  msgstr ""
1090
 
1091
- #: functions/interface.php:309
1092
  msgid "Database Every Two Weeks"
1093
  msgstr ""
1094
 
1095
- #: functions/interface.php:310
1096
  msgid "Complete Monthly"
1097
  msgstr ""
1098
 
1099
- #: functions/interface.php:311
1100
  msgid "File Monthly"
1101
  msgstr ""
1102
 
1103
- #: functions/interface.php:312
1104
  msgid "Database Monthly"
1105
  msgstr ""
1106
 
1107
- #: functions/interface.php:313
1108
  msgid "Complete Manually"
1109
  msgstr ""
1110
 
1111
- #: functions/interface.php:314
1112
  msgid "File Manually"
1113
  msgstr ""
1114
 
1115
- #: functions/interface.php:315
1116
  msgid "Database Manually"
1117
  msgstr ""
1118
 
@@ -1135,14 +1219,14 @@ msgstr ""
1135
  msgid "http://hmn.md/"
1136
  msgstr ""
1137
 
1138
- #: admin/schedule-sentence.php:125
1139
  msgctxt ""
1140
  "1: Backup Type 2: Total size of backup 3: Schedule 4: Number of backups to "
1141
  "store"
1142
  msgid "Backup my %1$s %2$s %3$s, %4$s."
1143
  msgstr ""
1144
 
1145
- #: functions/interface.php:286
1146
  msgctxt "backups count"
1147
  msgid "One backup completed"
1148
  msgid_plural "%1$s backups completed"
2
  # This file is distributed under the GPL-2+.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: BackUpWordPress 3.5\n"
6
  "Report-Msgid-Bugs-To: backupwordpress@hmn.md\n"
7
+ "POT-Creation-Date: 2016-03-31 17:13: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"
13
  "Language-Team: Human Made Limited\n"
14
  "X-Generator: grunt-wp-i18n 0.5.4\n"
15
 
16
+ #: admin/actions.php:188
17
  msgid "The schedule ID was not provided. Aborting."
18
  msgstr ""
19
 
20
+ #: admin/actions.php:245
21
  msgid "Backup type cannot be empty"
22
  msgstr ""
23
 
24
+ #: admin/actions.php:247
25
  msgid "Invalid backup type"
26
  msgstr ""
27
 
28
+ #: admin/actions.php:258
29
  msgid "Schedule cannot be empty"
30
  msgstr ""
31
 
32
+ #: admin/actions.php:260
33
  msgid "Invalid schedule"
34
  msgstr ""
35
 
36
+ #: admin/actions.php:271
37
  msgid "Day of the week must be a valid, lowercase day name"
38
  msgstr ""
39
 
40
+ #: admin/actions.php:287
41
  msgid "Day of month must be between 1 and 31"
42
  msgstr ""
43
 
44
+ #: admin/actions.php:303
45
  msgid "Hours must be between 0 and 23"
46
  msgstr ""
47
 
48
+ #: admin/actions.php:319
49
  msgid "Minutes must be between 0 and 59"
50
  msgstr ""
51
 
52
+ #: admin/actions.php:330
53
  msgid "Max backups can't be empty"
54
  msgstr ""
55
 
56
+ #: admin/actions.php:332
57
  msgid "Max backups must be a number"
58
  msgstr ""
59
 
60
+ #: admin/actions.php:334
61
  msgid "Max backups must be greater than 0"
62
  msgstr ""
63
 
64
+ #: admin/actions.php:336
65
+ msgid ""
66
+ "Storing %s backups would use %s of disk space but your server only has %s "
67
+ "free."
68
+ msgstr ""
69
+
70
+ #: admin/actions.php:636 admin/actions.php:642
71
  msgid "BackUpWordPress has detected a problem."
72
  msgstr ""
73
 
74
+ #: admin/actions.php:636
75
  msgid ""
76
  "%1$s is returning a %2$s response which could mean cron jobs aren't getting "
77
  "fired properly. BackUpWordPress relies on wp-cron to run scheduled backups. "
78
  "See the %3$s for more details."
79
  msgstr ""
80
 
81
+ #: admin/actions.php:642
82
  msgid ""
83
  "%1$s is returning a %2$s response which could mean cron jobs aren't getting "
84
  "fired properly. BackUpWordPress relies on wp-cron to run scheduled backups, "
112
  "settings. %4$s. Defined %5$s will be highlighted."
113
  msgstr ""
114
 
115
+ #: admin/constants.php:9 admin/menu.php:92
116
  msgid "Constants"
117
  msgstr ""
118
 
122
 
123
  #: admin/constants.php:20 admin/constants.php:36 admin/constants.php:52
124
  #: admin/constants.php:68 admin/constants.php:84 admin/constants.php:100
125
+ #: admin/constants.php:116 classes/class-email-service.php:64
126
  msgid "You've set it to: %s"
127
  msgstr ""
128
 
134
 
135
  #: admin/constants.php:23 admin/constants.php:39 admin/constants.php:55
136
  #: admin/constants.php:71 admin/constants.php:87 admin/constants.php:103
137
+ #: admin/constants.php:119 classes/class-email-service.php:67
138
  msgid "e.g."
139
  msgstr ""
140
 
199
  msgid "Yes, I want to enable support"
200
  msgstr ""
201
 
202
+ #: admin/extensions.php:11
203
+ msgid "&larr; Backups"
204
+ msgstr ""
205
+
206
+ #: admin/extensions.php:13 admin/menu.php:17
207
+ msgid "BackUpWordPress Extensions"
208
+ msgstr ""
209
+
210
+ #: admin/extensions.php:18
211
+ msgid ""
212
+ "Extend BackUpWordPress by installing extensions. Extensions allows you to "
213
+ "pick and choose the exact features you need whilst also supporting us, the "
214
+ "developers, so we can continue working on BackUpWordPress."
215
+ msgstr ""
216
+
217
+ #: admin/extensions.php:36
218
+ msgid "Remote Storage"
219
+ msgstr ""
220
+
221
+ #: admin/extensions.php:38
222
+ msgid ""
223
+ "It's important to store your backups somewhere other than on your site. "
224
+ "Using the extensions below you can easily push your backups to one or more "
225
+ "Cloud providers."
226
+ msgstr ""
227
+
228
+ #: admin/extensions.php:75
229
+ msgid "This extension is already installed"
230
+ msgstr ""
231
+
232
+ #: admin/extensions.php:75
233
+ msgid "Installed"
234
+ msgstr ""
235
+
236
+ #: admin/extensions.php:79
237
+ msgid "Buy Now &dollar;%s"
238
+ msgstr ""
239
+
240
+ #: admin/extensions.php:87
241
+ msgid "More information about %s"
242
+ msgstr ""
243
+
244
+ #: admin/extensions.php:87
245
+ msgid "More Details"
246
+ msgstr ""
247
+
248
+ #: admin/extensions.php:133
249
+ msgid "A newer version (%1$s) is available. <a href=\"%2$s\">Update now!</a>"
250
+ msgstr ""
251
+
252
+ #: admin/extensions.php:136
253
+ msgid "You have the latest version"
254
+ msgstr ""
255
+
256
+ #: admin/extensions.php:151
257
+ msgid "Last Updated:"
258
+ msgstr ""
259
+
260
+ #: admin/extensions.php:151
261
+ msgid "%s ago"
262
+ msgstr ""
263
+
264
  #: admin/faq.php:2
265
  msgid "Where does BackUpWordPress store the backup files?"
266
  msgstr ""
434
  "emailing backupwordpress@hmn.md"
435
  msgstr ""
436
 
437
+ #: admin/menu.php:12
438
+ msgid "Manage Backups | BackUpWordPress"
439
  msgstr ""
440
 
441
+ #: admin/menu.php:12 admin/menu.php:14 admin/menu.php:55
442
  msgid "Backups"
443
  msgstr ""
444
 
445
+ #: admin/menu.php:14
446
+ msgid "Manage Backups"
447
+ msgstr ""
448
+
449
+ #: admin/menu.php:17
450
+ msgid "Extensions"
451
+ msgstr ""
452
+
453
+ #: admin/menu.php:86
454
  msgid "FAQ"
455
  msgstr ""
456
 
457
+ #: admin/menu.php:105
458
  msgid "Server Info"
459
  msgstr ""
460
 
461
+ #: admin/menu.php:112
462
  msgid "For more information:"
463
  msgstr ""
464
 
465
+ #: admin/menu.php:112
466
  msgid "Support Forums"
467
  msgstr ""
468
 
469
+ #: admin/menu.php:112
470
  msgid "Help with translation"
471
  msgstr ""
472
 
473
+ #: admin/page.php:17
474
  msgid "Support"
475
  msgstr ""
476
 
477
+ #: admin/page.php:20
478
  msgid "Enable Support"
479
  msgstr ""
480
 
481
+ #: admin/page.php:29
482
  msgid ""
483
  "If you're finding BackUpWordPress useful, please %1$s rate it on the plugin "
484
  "directory%2$s."
533
  msgid "Status"
534
  msgstr ""
535
 
536
+ #: admin/schedule-form-excludes.php:162 admin/schedule-form-excludes.php:263
537
  msgid "%s of %s"
538
  msgstr ""
539
 
541
  msgid "Refresh"
542
  msgstr ""
543
 
544
+ #: admin/schedule-form-excludes.php:177 admin/schedule-form-excludes.php:294
545
  msgid "Symlink"
546
  msgstr ""
547
 
548
+ #: admin/schedule-form-excludes.php:179 admin/schedule-form-excludes.php:296
549
  msgid "Folder"
550
  msgstr ""
551
 
552
+ #: admin/schedule-form-excludes.php:298
553
  msgid "File"
554
  msgstr ""
555
 
556
+ #: admin/schedule-form-excludes.php:307
557
  msgid "Unreadable files won't be backed up."
558
  msgstr ""
559
 
560
+ #: admin/schedule-form-excludes.php:307
561
  msgid "Unreadable"
562
  msgstr ""
563
 
564
+ #: admin/schedule-form-excludes.php:311
565
  msgid "Excluded"
566
  msgstr ""
567
 
568
+ #: admin/schedule-form-excludes.php:326
569
  msgid "Exclude &rarr;"
570
  msgstr ""
571
 
572
+ #: admin/schedule-form-excludes.php:339
573
  msgid "This folder is empty"
574
  msgstr ""
575
 
576
+ #: admin/schedule-form-excludes.php:349 admin/schedule-form.php:204
577
+ #: admin/schedule-settings.php:85
578
  msgid "Done"
579
  msgstr ""
580
 
726
  msgid "store the last %1$s backups in %2$s"
727
  msgstr ""
728
 
729
+ #: admin/schedule-sentence.php:128
730
  msgid "Send a copy of each backup to %s."
731
  msgstr ""
732
 
733
+ #: admin/schedule-sentence.php:160
734
  msgid "Backups will be compressed and should be smaller than this."
735
  msgstr ""
736
 
737
+ #: admin/schedule-sentence.php:162
738
  msgid "this shouldn't take long&hellip;"
739
  msgstr ""
740
 
741
+ #: admin/schedule-sentence.php:162
742
  msgid "calculating the size of your site&hellip;"
743
  msgstr ""
744
 
750
  msgid "Excludes"
751
  msgstr ""
752
 
753
+ #: admin/schedule-settings.php:30 functions/interface.php:36
754
  msgid "Delete"
755
  msgstr ""
756
 
757
+ #: admin/upsell.php:9
758
+ msgid "Store your backups securely in the Cloud with %1$sour extensions%2$s"
 
 
 
 
 
 
759
  msgstr ""
760
 
761
  #: classes/backup/class-backup.php:57
790
  msgid "Backup Failed"
791
  msgstr ""
792
 
793
+ #: classes/class-email-service.php:30
794
  msgid "Email notification"
795
  msgstr ""
796
 
797
+ #: classes/class-email-service.php:36
798
  msgid ""
799
  "Receive a notification email when a backup completes. If the backup is "
800
  "small enough (&lt; %s), then it will be attached to the email. Separate "
801
  "multiple email addresses with a comma."
802
  msgstr ""
803
 
804
+ #: classes/class-email-service.php:67
805
  msgid ""
806
  "The maximum filesize of your backup that will be attached to your "
807
  "notification emails . Defaults to %s."
808
  msgstr ""
809
 
810
+ #: classes/class-email-service.php:86
811
  msgid "Send an email notification to %s"
812
  msgstr ""
813
 
814
+ #: classes/class-email-service.php:121
815
  msgid "%s isn't a valid email"
816
  msgstr ""
817
 
818
+ #: classes/class-email-service.php:177 classes/class-webhook-service.php:59
819
  msgid "Backup of %s Failed"
820
  msgstr ""
821
 
822
+ #: classes/class-email-service.php:179
823
  msgid "BackUpWordPress was unable to backup your site %1$s."
824
  msgstr ""
825
 
826
+ #: classes/class-email-service.php:179
827
  msgid "Here are the errors that we've encountered:"
828
  msgstr ""
829
 
830
+ #: classes/class-email-service.php:179
831
  msgid ""
832
  "If the errors above look like Martian, forward this email to %3$s and we'll "
833
  "take a look"
834
  msgstr ""
835
 
836
+ #: classes/class-email-service.php:179
837
  msgid ""
838
  "Kind Regards,\n"
839
  "The Apologetic BackUpWordPress Backup Emailing Robot"
840
  msgstr ""
841
 
842
+ #: classes/class-email-service.php:187
843
  msgid "Backup of %s"
844
  msgstr ""
845
 
846
+ #: classes/class-email-service.php:192 classes/class-email-service.php:201
847
  msgid "BackUpWordPress has completed a backup of your site %1$s."
848
  msgstr ""
849
 
850
+ #: classes/class-email-service.php:192
851
  msgid "The backup file should be attached to this email."
852
  msgstr ""
853
 
854
+ #: classes/class-email-service.php:192 classes/class-email-service.php:201
855
  msgid "You can download the backup file by clicking the link below:"
856
  msgstr ""
857
 
858
+ #: classes/class-email-service.php:192 classes/class-email-service.php:201
859
  msgid ""
860
  "Kind Regards,\n"
861
  "The Happy BackUpWordPress Backup Emailing Robot"
862
  msgstr ""
863
 
864
+ #: classes/class-email-service.php:201
865
  msgid "Unfortunately, the backup file was too large to attach to this email."
866
  msgstr ""
867
 
868
+ #: classes/class-path.php:341
869
  msgid "This %s file ensures that other people cannot download your backup files."
870
  msgstr ""
871
 
872
+ #: classes/class-plugin.php:240
873
  msgid "Update"
874
  msgstr ""
875
 
876
+ #: classes/class-plugin.php:241
877
  msgid "Cancel"
878
  msgstr ""
879
 
880
+ #: classes/class-plugin.php:242
881
  msgid ""
882
  "Are you sure you want to delete this schedule? All of its backups will also "
883
  "be deleted."
884
  msgstr ""
885
 
886
+ #: classes/class-plugin.php:242 classes/class-plugin.php:243
887
+ #: classes/class-plugin.php:244 classes/class-plugin.php:245
888
  msgid "'Cancel' to go back, 'OK' to delete."
889
  msgstr ""
890
 
891
+ #: classes/class-plugin.php:243
892
  msgid "Are you sure you want to delete this backup?"
893
  msgstr ""
894
 
895
+ #: classes/class-plugin.php:244
896
  msgid "Are you sure you want to remove this exclude rule?"
897
  msgstr ""
898
 
899
+ #: classes/class-plugin.php:245
900
  msgid ""
901
  "Reducing the number of backups that are stored on this server will cause "
902
  "some of your existing backups to be deleted. Are you sure that's what you "
903
  "want?"
904
  msgstr ""
905
 
906
+ #: classes/class-plugin.php:444
907
+ #. translators: %1$s and %2$s expand to anchor tags linking to the new
908
+ #. extensions page.
909
+ msgid ""
910
+ "Thanks for updating BackUpWordPress, why not check out %1$sour "
911
+ "extensions?%2$s"
912
+ msgstr ""
913
+
914
+ #: classes/class-plugin.php:454
915
+ msgid "Dismiss this notice."
916
+ msgstr ""
917
+
918
  #: classes/class-scheduled-backup.php:321
919
  msgid "Argument 1 for %s must be a valid cron recurrence or \"manually\""
920
  msgstr ""
921
 
922
+ #: classes/class-scheduled-backup.php:427 functions/interface.php:267
923
  msgid "Starting backup..."
924
  msgstr ""
925
 
926
+ #: classes/class-scheduled-backup.php:429
927
+ #: classes/class-scheduled-backup.php:444
928
  msgid "Deleting old backups..."
929
  msgstr ""
930
 
931
+ #: classes/class-scheduled-backup.php:544
932
  #. translators: min=minute
933
  msgid "%s min"
934
  msgid_plural "%s mins"
935
  msgstr[0] ""
936
  msgstr[1] ""
937
 
938
+ #: classes/class-scheduled-backup.php:554
939
  msgid "%s hour"
940
  msgid_plural "%s hours"
941
  msgstr[0] ""
942
  msgstr[1] ""
943
 
944
+ #: classes/class-scheduled-backup.php:615
945
  msgid "Argument 1 for %s must be a non-empty string"
946
  msgstr ""
947
 
948
+ #: classes/class-scheduled-backup.php:620
949
  msgid "%s doesn't exist"
950
  msgstr ""
951
 
952
+ #: classes/class-scheduled-backup.php:625
953
  msgid "That backup wasn't created by this schedule"
954
  msgstr ""
955
 
956
+ #: classes/class-services.php:81
957
  msgid "Argument 1 for %s must be a valid filepath"
958
  msgstr ""
959
 
960
+ #: classes/class-services.php:97
961
  msgid "Argument 1 for %s must be a registered service"
962
  msgstr ""
963
 
964
+ #: classes/class-services.php:115 classes/deprecated.php:81
965
  msgid "Argument 1 for %s must be a valid class"
966
  msgstr ""
967
 
969
  msgid "BackUpWordPress"
970
  msgstr ""
971
 
972
+ #: classes/class-setup.php:169
973
  msgid ""
974
  "BackUpWordPress requires PHP version %1$s or later and WordPress version "
975
  "%2$s or later to run. It has not been activated. %3$s%4$s%5$sLearn more%6$s"
979
  msgid "Error: %s"
980
  msgstr ""
981
 
982
+ #: functions/core.php:331
983
  msgid "BackUpWordPress has set up your default schedules."
984
  msgstr ""
985
 
986
+ #: functions/core.php:331
987
  msgid ""
988
  "By default BackUpWordPress performs a daily backup of your database and a "
989
  "weekly backup of your database &amp; files. You can modify these schedules."
990
  msgstr ""
991
 
992
+ #: functions/core.php:347
993
  msgid "Once Hourly"
994
  msgstr ""
995
 
996
+ #: functions/core.php:348
997
  msgid "Twice Daily"
998
  msgstr ""
999
 
1000
+ #: functions/core.php:349
1001
  msgid "Once Daily"
1002
  msgstr ""
1003
 
1004
+ #: functions/core.php:350
1005
  msgid "Once Weekly"
1006
  msgstr ""
1007
 
1008
+ #: functions/core.php:351
1009
  msgid "Once Every Two Weeks"
1010
  msgstr ""
1011
 
1012
+ #: functions/core.php:352
1013
  msgid "Once Monthly"
1014
  msgstr ""
1015
 
1016
+ #: functions/core.php:371
1017
  msgid "You can only delete directories inside your WordPress installation"
1018
  msgstr ""
1019
 
1025
  msgid "BackUpWordPress detected issues with your last backup."
1026
  msgstr ""
1027
 
1028
+ #: functions/interface.php:147
 
 
 
 
 
1029
  msgid ""
1030
  "The backups directory can't be created because your %s directory isn't "
1031
  "writable. Please create the folder manually."
1032
  msgstr ""
1033
 
1034
+ #: functions/interface.php:151
1035
  msgid "The backups directory isn't writable. Please fix the permissions."
1036
  msgstr ""
1037
 
1038
+ #: functions/interface.php:155
1039
  msgid ""
1040
  "%1$s is running in %2$s, please contact your host and ask them to disable "
1041
  "it. BackUpWordPress may not work correctly whilst %3$s is on."
1042
  msgstr ""
1043
 
1044
+ #: functions/interface.php:155
1045
  msgid "http://php.net/manual/en/features.safe-mode.php"
1046
  msgstr ""
1047
 
1048
+ #: functions/interface.php:155
1049
  msgid "Safe Mode"
1050
  msgstr ""
1051
 
1052
+ #: functions/interface.php:162
1053
  msgid ""
1054
  "Your server has an %1$s restriction in effect and your custom backups "
1055
  "directory (%2$s) is not within the allowed path(s): (%3$s)."
1056
  msgstr ""
1057
 
1058
+ #: functions/interface.php:165
1059
  msgid "Your custom path does not exist"
1060
  msgstr ""
1061
 
1062
+ #: functions/interface.php:170
1063
  msgid ""
1064
  "Your custom backups directory %1$s doesn't exist and can't be created, your "
1065
  "backups will be saved to %2$s instead."
1066
  msgstr ""
1067
 
1068
+ #: functions/interface.php:174
1069
  msgid ""
1070
  "Your custom backups directory %1$s isn't writable, new backups will be "
1071
  "saved to %2$s instead."
1072
  msgstr ""
1073
 
1074
+ #: functions/interface.php:181
1075
  msgid "Your site root path %s isn't readable."
1076
  msgstr ""
1077
 
1078
+ #: functions/interface.php:185 functions/interface.php:189
1079
+ msgid ""
1080
+ "Your site cannot be backed up because your server doesn't support %1$s or "
1081
+ "%2$s. Please contact your host and ask them to enable them."
1082
+ msgstr ""
1083
+
1084
+ #: functions/interface.php:193
1085
  msgid ""
1086
+ "Your server only has %s of disk space left which probably isn't enough to "
1087
+ "complete a backup. Try deleting some existing backups or other files to "
1088
+ "free up space."
1089
  msgstr ""
1090
 
1091
+ #: functions/interface.php:234
1092
  msgid "Database and Files"
1093
  msgstr ""
1094
 
1095
+ #: functions/interface.php:238
1096
  msgid "Files"
1097
  msgstr ""
1098
 
1099
+ #: functions/interface.php:242
1100
  msgid "Database"
1101
  msgstr ""
1102
 
1103
+ #: functions/interface.php:249
1104
  msgid "Legacy"
1105
  msgstr ""
1106
 
1107
+ #: functions/interface.php:266
1108
  msgid "Started %s ago"
1109
  msgstr ""
1110
 
1111
+ #: functions/interface.php:268
1112
  msgid "cancel"
1113
  msgstr ""
1114
 
1115
+ #: functions/interface.php:286
1116
  msgid "No backups completed"
1117
  msgstr ""
1118
 
1119
+ #: functions/interface.php:297
1120
  msgid "Complete Hourly"
1121
  msgstr ""
1122
 
1123
+ #: functions/interface.php:298
1124
  msgid "File Hourly"
1125
  msgstr ""
1126
 
1127
+ #: functions/interface.php:299
1128
  msgid "Database Hourly"
1129
  msgstr ""
1130
 
1131
+ #: functions/interface.php:300
1132
  msgid "Complete Twice Daily"
1133
  msgstr ""
1134
 
1135
+ #: functions/interface.php:301
1136
  msgid "File Twice Daily"
1137
  msgstr ""
1138
 
1139
+ #: functions/interface.php:302
1140
  msgid "Database Twice Daily"
1141
  msgstr ""
1142
 
1143
+ #: functions/interface.php:303
1144
  msgid "Complete Daily"
1145
  msgstr ""
1146
 
1147
+ #: functions/interface.php:304
1148
  msgid "File Daily"
1149
  msgstr ""
1150
 
1151
+ #: functions/interface.php:305
1152
  msgid "Database Daily"
1153
  msgstr ""
1154
 
1155
+ #: functions/interface.php:306
1156
  msgid "Complete Weekly"
1157
  msgstr ""
1158
 
1159
+ #: functions/interface.php:307
1160
  msgid "File Weekly"
1161
  msgstr ""
1162
 
1163
+ #: functions/interface.php:308
1164
  msgid "Database Weekly"
1165
  msgstr ""
1166
 
1167
+ #: functions/interface.php:309
1168
  msgid "Complete Every Two Weeks"
1169
  msgstr ""
1170
 
1171
+ #: functions/interface.php:310
1172
  msgid "File Every Two Weeks"
1173
  msgstr ""
1174
 
1175
+ #: functions/interface.php:311
1176
  msgid "Database Every Two Weeks"
1177
  msgstr ""
1178
 
1179
+ #: functions/interface.php:312
1180
  msgid "Complete Monthly"
1181
  msgstr ""
1182
 
1183
+ #: functions/interface.php:313
1184
  msgid "File Monthly"
1185
  msgstr ""
1186
 
1187
+ #: functions/interface.php:314
1188
  msgid "Database Monthly"
1189
  msgstr ""
1190
 
1191
+ #: functions/interface.php:315
1192
  msgid "Complete Manually"
1193
  msgstr ""
1194
 
1195
+ #: functions/interface.php:316
1196
  msgid "File Manually"
1197
  msgstr ""
1198
 
1199
+ #: functions/interface.php:317
1200
  msgid "Database Manually"
1201
  msgstr ""
1202
 
1219
  msgid "http://hmn.md/"
1220
  msgstr ""
1221
 
1222
+ #: admin/schedule-sentence.php:121
1223
  msgctxt ""
1224
  "1: Backup Type 2: Total size of backup 3: Schedule 4: Number of backups to "
1225
  "store"
1226
  msgid "Backup my %1$s %2$s %3$s, %4$s."
1227
  msgstr ""
1228
 
1229
+ #: functions/interface.php:288
1230
  msgctxt "backups count"
1231
  msgid "One backup completed"
1232
  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.4.2
6
- Stable tag: 3.5
7
 
8
  Simple automated backups of your WordPress-powered website.
9
 
@@ -82,15 +82,15 @@ The issue is that your `wp-cron.php` is not returning a `200` response when hit
82
 
83
  There are some things you can test to confirm this is the issue.
84
 
85
- * Are scheduled posts working? (They use wp-cron as well.)
86
 
87
- * Are you hosted on Heart Internet? (wp-cron may not be supported by Heart Internet, see below for work-around.)
88
 
89
- * If you click manual backup, does it work?
90
 
91
- * Try adding `define( 'ALTERNATE_WP_CRON', true );` to your `wp-config.php`. Do automatic backups work?
92
 
93
- * Is your site private (i.e. is it behind some kind of authentication, maintenance plugin, .htaccess)? If so, wp-cron won't work until you remove it. If you are and you temporarily remove the authentication, do backups start working?
94
 
95
  Report the results to our support team for further help. To do this, either enable support from your Admin Dashboard (recommended), or email backupwordpress@hmn.md
96
 
@@ -158,6 +158,15 @@ users should see major improvements to reliability.
158
 
159
  == Changelog ==
160
 
 
 
 
 
 
 
 
 
 
161
  ### 3.5 / 2016-03-10
162
 
163
  * Reduce duplication and improve code readability when echoing filesizes
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.4.2
6
+ Stable tag: 3.6.0
7
 
8
  Simple automated backups of your WordPress-powered website.
9
 
82
 
83
  There are some things you can test to confirm this is the issue.
84
 
85
+ * Are scheduled posts working? (They use wp-cron as well.)
86
 
87
+ * Are you hosted on Heart Internet? (wp-cron may not be supported by Heart Internet, see below for work-around.)
88
 
89
+ * If you click manual backup, does it work?
90
 
91
+ * Try adding `define( 'ALTERNATE_WP_CRON', true );` to your `wp-config.php`. Do automatic backups work?
92
 
93
+ * Is your site private (i.e. is it behind some kind of authentication, maintenance plugin, .htaccess)? If so, wp-cron won't work until you remove it. If you are and you temporarily remove the authentication, do backups start working?
94
 
95
  Report the results to our support team for further help. To do this, either enable support from your Admin Dashboard (recommended), or email backupwordpress@hmn.md
96
 
158
 
159
  == Changelog ==
160
 
161
+ ### 3.6.0 / 2016-03-31
162
+
163
+ * Fix a bug caused by using a function incompatible with min PHP version requirements
164
+ * Misc code quality improvements and bug fixes
165
+ * Fix bugs in the code responsible for admin notices
166
+ * Display disk space info
167
+ * Uninstall cleanup
168
+ * Introduce a dedicated extensions page
169
+
170
  ### 3.5 / 2016-03-10
171
 
172
  * Reduce duplication and improve code readability when echoing filesizes
uninstall.php CHANGED
@@ -12,9 +12,11 @@ global $wpdb;
12
 
13
  require_once dirname( __FILE__ ) . '/classes/class-path.php';
14
 
 
 
15
  // Delete the file manifest if it exists
16
- if ( file_exists( HM\BackUpWordPress\PATH::get_path() . '/.files' ) ) {
17
- unlink( HM\BackUpWordPress\PATH::get_path() . '/.files' );
18
  }
19
 
20
  // Get all schedule options with a SELECT query and delete them.
@@ -23,7 +25,7 @@ $schedules = $wpdb->get_col( $wpdb->prepare( "SELECT option_name FROM $wpdb->opt
23
  array_map( 'delete_option', $schedules );
24
 
25
  // Remove all the options
26
- array_map( 'delete_option', array( 'hmbkp_enable_support', 'hmbkp_plugin_version', 'hmbkp_path', 'hmbkp_default_path', 'hmbkp_upsell' ) );
27
 
28
  // Delete all transients
29
  array_map( 'delete_transient', array( 'hmbkp_plugin_data', 'hmbkp_directory_filesizes', 'hmbkp_directory_filesize_running', 'timeout_hmbkp_wp_cron_test_beacon', 'hmbkp_wp_cron_test_beacon' ) );
12
 
13
  require_once dirname( __FILE__ ) . '/classes/class-path.php';
14
 
15
+ $path = HM\BackUpWordPress\PATH::get_instance()->get_existing_path();
16
+
17
  // Delete the file manifest if it exists
18
+ if ( file_exists( $path . '/.files' ) ) {
19
+ unlink( $path . '/.files' );
20
  }
21
 
22
  // Get all schedule options with a SELECT query and delete them.
25
  array_map( 'delete_option', $schedules );
26
 
27
  // Remove all the options
28
+ array_map( 'delete_option', array( 'hmbkp_enable_support', 'hmbkp_plugin_version', 'hmbkp_path', 'hmbkp_default_path', 'hmbkp_upsell', 'hmbkp_notices' ) );
29
 
30
  // Delete all transients
31
  array_map( 'delete_transient', array( 'hmbkp_plugin_data', 'hmbkp_directory_filesizes', 'hmbkp_directory_filesize_running', 'timeout_hmbkp_wp_cron_test_beacon', 'hmbkp_wp_cron_test_beacon' ) );
vendor/composer/installed.json CHANGED
@@ -55,23 +55,23 @@
55
  },
56
  {
57
  "name": "symfony/finder",
58
- "version": "v2.8.3",
59
- "version_normalized": "2.8.3.0",
60
  "source": {
61
  "type": "git",
62
  "url": "https://github.com/symfony/finder.git",
63
- "reference": "877bb4b16ea573cc8c024e9590888fcf7eb7e0f7"
64
  },
65
  "dist": {
66
  "type": "zip",
67
- "url": "https://api.github.com/repos/symfony/finder/zipball/877bb4b16ea573cc8c024e9590888fcf7eb7e0f7",
68
- "reference": "877bb4b16ea573cc8c024e9590888fcf7eb7e0f7",
69
  "shasum": ""
70
  },
71
  "require": {
72
  "php": ">=5.3.9"
73
  },
74
- "time": "2016-02-22 16:12:45",
75
  "type": "library",
76
  "extra": {
77
  "branch-alias": {
@@ -106,23 +106,23 @@
106
  },
107
  {
108
  "name": "symfony/process",
109
- "version": "v2.8.3",
110
- "version_normalized": "2.8.3.0",
111
  "source": {
112
  "type": "git",
113
  "url": "https://github.com/symfony/process.git",
114
- "reference": "7dedd5b60550f33dca16dd7e94ef8aca8b67bbfe"
115
  },
116
  "dist": {
117
  "type": "zip",
118
- "url": "https://api.github.com/repos/symfony/process/zipball/7dedd5b60550f33dca16dd7e94ef8aca8b67bbfe",
119
- "reference": "7dedd5b60550f33dca16dd7e94ef8aca8b67bbfe",
120
  "shasum": ""
121
  },
122
  "require": {
123
  "php": ">=5.3.9"
124
  },
125
- "time": "2016-02-02 13:33:15",
126
  "type": "library",
127
  "extra": {
128
  "branch-alias": {
55
  },
56
  {
57
  "name": "symfony/finder",
58
+ "version": "v2.8.4",
59
+ "version_normalized": "2.8.4.0",
60
  "source": {
61
  "type": "git",
62
  "url": "https://github.com/symfony/finder.git",
63
+ "reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1"
64
  },
65
  "dist": {
66
  "type": "zip",
67
+ "url": "https://api.github.com/repos/symfony/finder/zipball/ca24cf2cd4e3826f571e0067e535758e73807aa1",
68
+ "reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1",
69
  "shasum": ""
70
  },
71
  "require": {
72
  "php": ">=5.3.9"
73
  },
74
+ "time": "2016-03-10 10:53:53",
75
  "type": "library",
76
  "extra": {
77
  "branch-alias": {
106
  },
107
  {
108
  "name": "symfony/process",
109
+ "version": "v2.8.4",
110
+ "version_normalized": "2.8.4.0",
111
  "source": {
112
  "type": "git",
113
  "url": "https://github.com/symfony/process.git",
114
+ "reference": "fb467471952ef5cf8497c029980e556b47545333"
115
  },
116
  "dist": {
117
  "type": "zip",
118
+ "url": "https://api.github.com/repos/symfony/process/zipball/fb467471952ef5cf8497c029980e556b47545333",
119
+ "reference": "fb467471952ef5cf8497c029980e556b47545333",
120
  "shasum": ""
121
  },
122
  "require": {
123
  "php": ">=5.3.9"
124
  },
125
+ "time": "2016-03-23 13:11:46",
126
  "type": "library",
127
  "extra": {
128
  "branch-alias": {
vendor/symfony/finder/Adapter/AbstractAdapter.php CHANGED
File without changes
vendor/symfony/finder/Adapter/AbstractFindAdapter.php CHANGED
File without changes
vendor/symfony/finder/Adapter/AdapterInterface.php CHANGED
File without changes
vendor/symfony/finder/Adapter/BsdFindAdapter.php CHANGED
File without changes
vendor/symfony/finder/Adapter/GnuFindAdapter.php CHANGED
File without changes
vendor/symfony/finder/Adapter/PhpAdapter.php CHANGED
File without changes
vendor/symfony/finder/CHANGELOG.md CHANGED
File without changes
vendor/symfony/finder/Comparator/Comparator.php CHANGED
File without changes
vendor/symfony/finder/Comparator/DateComparator.php CHANGED
File without changes
vendor/symfony/finder/Comparator/NumberComparator.php CHANGED
File without changes
vendor/symfony/finder/Exception/AccessDeniedException.php CHANGED
File without changes
vendor/symfony/finder/Exception/AdapterFailureException.php CHANGED
File without changes
vendor/symfony/finder/Exception/ExceptionInterface.php CHANGED
File without changes
vendor/symfony/finder/Exception/OperationNotPermitedException.php CHANGED
File without changes
vendor/symfony/finder/Exception/ShellCommandFailureException.php CHANGED
File without changes
vendor/symfony/finder/Expression/Expression.php CHANGED
File without changes
vendor/symfony/finder/Expression/Glob.php CHANGED
File without changes
vendor/symfony/finder/Expression/Regex.php CHANGED
File without changes
vendor/symfony/finder/Expression/ValueInterface.php CHANGED
File without changes
vendor/symfony/finder/Finder.php CHANGED
File without changes
vendor/symfony/finder/Glob.php CHANGED
File without changes
vendor/symfony/finder/Iterator/CustomFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/DateRangeFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/FilePathsIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/FileTypeFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/FilecontentFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/FilenameFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/FilterIterator.php CHANGED
@@ -39,11 +39,18 @@ abstract class FilterIterator extends \FilterIterator
39
  while ($iterator instanceof \OuterIterator) {
40
  $innerIterator = $iterator->getInnerIterator();
41
 
42
- if ($innerIterator instanceof \FilesystemIterator) {
 
 
 
 
 
 
43
  $innerIterator->next();
44
  $innerIterator->rewind();
45
  }
46
- $iterator = $iterator->getInnerIterator();
 
47
  }
48
 
49
  parent::rewind();
39
  while ($iterator instanceof \OuterIterator) {
40
  $innerIterator = $iterator->getInnerIterator();
41
 
42
+ if ($innerIterator instanceof RecursiveDirectoryIterator) {
43
+ // this condition is necessary for iterators to work properly with non-local filesystems like ftp
44
+ if ($innerIterator->isRewindable()) {
45
+ $innerIterator->next();
46
+ $innerIterator->rewind();
47
+ }
48
+ } elseif ($innerIterator instanceof \FilesystemIterator) {
49
  $innerIterator->next();
50
  $innerIterator->rewind();
51
  }
52
+
53
+ $iterator = $innerIterator;
54
  }
55
 
56
  parent::rewind();
vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/PathFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/SortableIterator.php CHANGED
File without changes
vendor/symfony/finder/LICENSE CHANGED
File without changes
vendor/symfony/finder/Shell/Command.php CHANGED
File without changes
vendor/symfony/finder/Shell/Shell.php CHANGED
File without changes
vendor/symfony/finder/SplFileInfo.php CHANGED
File without changes
vendor/symfony/finder/composer.json CHANGED
File without changes
vendor/symfony/finder/phpunit.xml.dist CHANGED
File without changes
vendor/symfony/process/CHANGELOG.md CHANGED
File without changes
vendor/symfony/process/Exception/ExceptionInterface.php CHANGED
File without changes
vendor/symfony/process/Exception/InvalidArgumentException.php CHANGED
File without changes
vendor/symfony/process/Exception/LogicException.php CHANGED
File without changes
vendor/symfony/process/Exception/ProcessFailedException.php CHANGED
File without changes
vendor/symfony/process/Exception/ProcessTimedOutException.php CHANGED
File without changes
vendor/symfony/process/Exception/RuntimeException.php CHANGED
File without changes
vendor/symfony/process/ExecutableFinder.php CHANGED
File without changes
vendor/symfony/process/LICENSE CHANGED
File without changes
vendor/symfony/process/PhpExecutableFinder.php CHANGED
File without changes
vendor/symfony/process/PhpProcess.php CHANGED
File without changes
vendor/symfony/process/Pipes/AbstractPipes.php CHANGED
@@ -29,6 +29,17 @@ abstract class AbstractPipes implements PipesInterface
29
  /** @var bool */
30
  private $blocked = true;
31
 
 
 
 
 
 
 
 
 
 
 
 
32
  /**
33
  * {@inheritdoc}
34
  */
@@ -71,4 +82,64 @@ abstract class AbstractPipes implements PipesInterface
71
 
72
  $this->blocked = false;
73
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  }
29
  /** @var bool */
30
  private $blocked = true;
31
 
32
+ public function __construct($input)
33
+ {
34
+ if (is_resource($input)) {
35
+ $this->input = $input;
36
+ } elseif (is_string($input)) {
37
+ $this->inputBuffer = $input;
38
+ } else {
39
+ $this->inputBuffer = (string) $input;
40
+ }
41
+ }
42
+
43
  /**
44
  * {@inheritdoc}
45
  */
82
 
83
  $this->blocked = false;
84
  }
85
+
86
+ /**
87
+ * Writes input to stdin.
88
+ */
89
+ protected function write()
90
+ {
91
+ if (!isset($this->pipes[0])) {
92
+ return;
93
+ }
94
+
95
+ $e = array();
96
+ $r = null !== $this->input ? array($this->input) : $e;
97
+ $w = array($this->pipes[0]);
98
+
99
+ // let's have a look if something changed in streams
100
+ if (false === $n = @stream_select($r, $w, $e, 0, 0)) {
101
+ return;
102
+ }
103
+
104
+ foreach ($w as $stdin) {
105
+ if (isset($this->inputBuffer[0])) {
106
+ $written = fwrite($stdin, $this->inputBuffer);
107
+ $this->inputBuffer = substr($this->inputBuffer, $written);
108
+ if (isset($this->inputBuffer[0])) {
109
+ return array($this->pipes[0]);
110
+ }
111
+ }
112
+
113
+ foreach ($r as $input) {
114
+ for (;;) {
115
+ $data = fread($input, self::CHUNK_SIZE);
116
+ if (!isset($data[0])) {
117
+ break;
118
+ }
119
+ $written = fwrite($stdin, $data);
120
+ $data = substr($data, $written);
121
+ if (isset($data[0])) {
122
+ $this->inputBuffer = $data;
123
+
124
+ return array($this->pipes[0]);
125
+ }
126
+ }
127
+ if (!isset($data[0]) && feof($input)) {
128
+ // no more data to read on input resource
129
+ // use an empty buffer in the next reads
130
+ $this->input = null;
131
+ }
132
+ }
133
+ }
134
+
135
+ // no input to read on resource, buffer is empty
136
+ if (null === $this->input && !isset($this->inputBuffer[0])) {
137
+ fclose($this->pipes[0]);
138
+ unset($this->pipes[0]);
139
+ }
140
+
141
+ if (!$w) {
142
+ return array($this->pipes[0]);
143
+ }
144
+ }
145
  }
vendor/symfony/process/Pipes/PipesInterface.php CHANGED
File without changes
vendor/symfony/process/Pipes/UnixPipes.php CHANGED
@@ -35,11 +35,7 @@ class UnixPipes extends AbstractPipes
35
  $this->ptyMode = (bool) $ptyMode;
36
  $this->disableOutput = (bool) $disableOutput;
37
 
38
- if (is_resource($input)) {
39
- $this->input = $input;
40
- } else {
41
- $this->inputBuffer = (string) $input;
42
- }
43
  }
44
 
45
  public function __destruct()
@@ -98,36 +94,15 @@ class UnixPipes extends AbstractPipes
98
  */
99
  public function readAndWrite($blocking, $close = false)
100
  {
101
- // only stdin is left open, job has been done !
102
- // we can now close it
103
- if (1 === count($this->pipes) && array(0) === array_keys($this->pipes)) {
104
- fclose($this->pipes[0]);
105
- unset($this->pipes[0]);
106
- }
107
-
108
- if (empty($this->pipes)) {
109
- return array();
110
- }
111
-
112
  $this->unblock();
 
113
 
114
- $read = array();
115
-
116
- if (null !== $this->input) {
117
- // if input is a resource, let's add it to stream_select argument to
118
- // fill a buffer
119
- $r = array_merge($this->pipes, array('input' => $this->input));
120
- } else {
121
- $r = $this->pipes;
122
- }
123
- // discard read on stdin
124
  unset($r[0]);
125
 
126
- $w = isset($this->pipes[0]) ? array($this->pipes[0]) : null;
127
- $e = null;
128
-
129
  // let's have a look if something changed in streams
130
- if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
131
  // if a system call has been interrupted, forget about it, let's try again
132
  // otherwise, an error occurred, let's reset pipes
133
  if (!$this->hasSystemCallBeenInterrupted()) {
@@ -137,57 +112,26 @@ class UnixPipes extends AbstractPipes
137
  return $read;
138
  }
139
 
140
- // nothing has changed
141
- if (0 === $n) {
142
- return $read;
143
- }
144
-
145
  foreach ($r as $pipe) {
146
  // prior PHP 5.4 the array passed to stream_select is modified and
147
  // lose key association, we have to find back the key
148
- $type = (false !== $found = array_search($pipe, $this->pipes)) ? $found : 'input';
149
- $data = '';
150
- while ('' !== $dataread = (string) fread($pipe, self::CHUNK_SIZE)) {
151
- $data .= $dataread;
152
- }
153
 
154
- if ('' !== $data) {
155
- if ($type === 'input') {
156
- $this->inputBuffer .= $data;
157
- } else {
158
- $read[$type] = $data;
159
- }
160
- }
161
 
162
- if (false === $data || (true === $close && feof($pipe) && '' === $data)) {
163
- if ($type === 'input') {
164
- // no more data to read on input resource
165
- // use an empty buffer in the next reads
166
- $this->input = null;
167
- } else {
168
- fclose($this->pipes[$type]);
169
- unset($this->pipes[$type]);
170
- }
171
  }
172
- }
173
 
174
- if (null !== $w && 0 < count($w)) {
175
- while (strlen($this->inputBuffer)) {
176
- $written = fwrite($w[0], $this->inputBuffer, 2 << 18); // write 512k
177
- if ($written > 0) {
178
- $this->inputBuffer = (string) substr($this->inputBuffer, $written);
179
- } else {
180
- break;
181
- }
182
  }
183
  }
184
 
185
- // no input to read on resource, buffer is empty and stdin still open
186
- if ('' === $this->inputBuffer && null === $this->input && isset($this->pipes[0])) {
187
- fclose($this->pipes[0]);
188
- unset($this->pipes[0]);
189
- }
190
-
191
  return $read;
192
  }
193
 
35
  $this->ptyMode = (bool) $ptyMode;
36
  $this->disableOutput = (bool) $disableOutput;
37
 
38
+ parent::__construct($input);
 
 
 
 
39
  }
40
 
41
  public function __destruct()
94
  */
95
  public function readAndWrite($blocking, $close = false)
96
  {
 
 
 
 
 
 
 
 
 
 
 
97
  $this->unblock();
98
+ $w = $this->write();
99
 
100
+ $read = $e = array();
101
+ $r = $this->pipes;
 
 
 
 
 
 
 
 
102
  unset($r[0]);
103
 
 
 
 
104
  // let's have a look if something changed in streams
105
+ if (($r || $w) && false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
106
  // if a system call has been interrupted, forget about it, let's try again
107
  // otherwise, an error occurred, let's reset pipes
108
  if (!$this->hasSystemCallBeenInterrupted()) {
112
  return $read;
113
  }
114
 
 
 
 
 
 
115
  foreach ($r as $pipe) {
116
  // prior PHP 5.4 the array passed to stream_select is modified and
117
  // lose key association, we have to find back the key
118
+ $read[$type = array_search($pipe, $this->pipes, true)] = '';
 
 
 
 
119
 
120
+ do {
121
+ $data = fread($pipe, self::CHUNK_SIZE);
122
+ $read[$type] .= $data;
123
+ } while (isset($data[0]));
 
 
 
124
 
125
+ if (!isset($read[$type][0])) {
126
+ unset($read[$type]);
 
 
 
 
 
 
 
127
  }
 
128
 
129
+ if ($close && feof($pipe)) {
130
+ fclose($pipe);
131
+ unset($this->pipes[$type]);
 
 
 
 
 
132
  }
133
  }
134
 
 
 
 
 
 
 
135
  return $read;
136
  }
137
 
vendor/symfony/process/Pipes/WindowsPipes.php CHANGED
@@ -52,17 +52,13 @@ class WindowsPipes extends AbstractPipes
52
  Process::STDERR => tempnam(sys_get_temp_dir(), 'err_sf_proc'),
53
  );
54
  foreach ($this->files as $offset => $file) {
55
- if (false === $file || false === $this->fileHandles[$offset] = fopen($file, 'rb')) {
56
  throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable');
57
  }
58
  }
59
  }
60
 
61
- if (is_resource($input)) {
62
- $this->input = $input;
63
- } else {
64
- $this->inputBuffer = $input;
65
- }
66
  }
67
 
68
  public function __destruct()
@@ -109,28 +105,26 @@ class WindowsPipes extends AbstractPipes
109
  */
110
  public function readAndWrite($blocking, $close = false)
111
  {
112
- $this->write($blocking, $close);
113
-
114
- $read = array();
115
- $fh = $this->fileHandles;
116
- foreach ($fh as $type => $fileHandle) {
117
- if (0 !== fseek($fileHandle, $this->readBytes[$type])) {
118
- continue;
119
- }
120
- $data = '';
121
- $dataread = null;
122
- while (!feof($fileHandle)) {
123
- if (false !== $dataread = fread($fileHandle, self::CHUNK_SIZE)) {
124
- $data .= $dataread;
125
- }
126
  }
127
- if (0 < $length = strlen($data)) {
128
- $this->readBytes[$type] += $length;
 
 
 
 
129
  $read[$type] = $data;
130
  }
131
-
132
- if (false === $dataread || (true === $close && feof($fileHandle) && '' === $data)) {
133
- fclose($this->fileHandles[$type]);
134
  unset($this->fileHandles[$type]);
135
  }
136
  }
@@ -143,7 +137,7 @@ class WindowsPipes extends AbstractPipes
143
  */
144
  public function areOpen()
145
  {
146
- return (bool) $this->pipes && (bool) $this->fileHandles;
147
  }
148
 
149
  /**
@@ -183,71 +177,4 @@ class WindowsPipes extends AbstractPipes
183
  }
184
  $this->files = array();
185
  }
186
-
187
- /**
188
- * Writes input to stdin.
189
- *
190
- * @param bool $blocking
191
- * @param bool $close
192
- */
193
- private function write($blocking, $close)
194
- {
195
- if (empty($this->pipes)) {
196
- return;
197
- }
198
-
199
- $this->unblock();
200
-
201
- $r = null !== $this->input ? array('input' => $this->input) : null;
202
- $w = isset($this->pipes[0]) ? array($this->pipes[0]) : null;
203
- $e = null;
204
-
205
- // let's have a look if something changed in streams
206
- if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
207
- // if a system call has been interrupted, forget about it, let's try again
208
- // otherwise, an error occurred, let's reset pipes
209
- if (!$this->hasSystemCallBeenInterrupted()) {
210
- $this->pipes = array();
211
- }
212
-
213
- return;
214
- }
215
-
216
- // nothing has changed
217
- if (0 === $n) {
218
- return;
219
- }
220
-
221
- if (null !== $w && 0 < count($r)) {
222
- $data = '';
223
- while ($dataread = fread($r['input'], self::CHUNK_SIZE)) {
224
- $data .= $dataread;
225
- }
226
-
227
- $this->inputBuffer .= $data;
228
-
229
- if (false === $data || (true === $close && feof($r['input']) && '' === $data)) {
230
- // no more data to read on input resource
231
- // use an empty buffer in the next reads
232
- $this->input = null;
233
- }
234
- }
235
-
236
- if (null !== $w && 0 < count($w)) {
237
- while (strlen($this->inputBuffer)) {
238
- $written = fwrite($w[0], $this->inputBuffer, 2 << 18);
239
- if ($written > 0) {
240
- $this->inputBuffer = (string) substr($this->inputBuffer, $written);
241
- } else {
242
- break;
243
- }
244
- }
245
- }
246
-
247
- // no input to read on resource, buffer is empty and stdin still open
248
- if ('' === $this->inputBuffer && null === $this->input && isset($this->pipes[0])) {
249
- fclose($this->pipes[0]);
250
- unset($this->pipes[0]);
251
- }
252
- }
253
  }
52
  Process::STDERR => tempnam(sys_get_temp_dir(), 'err_sf_proc'),
53
  );
54
  foreach ($this->files as $offset => $file) {
55
+ if (false === $file || false === $this->fileHandles[$offset] = @fopen($file, 'rb')) {
56
  throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable');
57
  }
58
  }
59
  }
60
 
61
+ parent::__construct($input);
 
 
 
 
62
  }
63
 
64
  public function __destruct()
105
  */
106
  public function readAndWrite($blocking, $close = false)
107
  {
108
+ $this->unblock();
109
+ $w = $this->write();
110
+ $read = $r = $e = array();
111
+
112
+ if ($blocking) {
113
+ if ($w) {
114
+ @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
115
+ } elseif ($this->fileHandles) {
116
+ usleep(Process::TIMEOUT_PRECISION * 1E6);
 
 
 
 
 
117
  }
118
+ }
119
+ foreach ($this->fileHandles as $type => $fileHandle) {
120
+ $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
121
+
122
+ if (isset($data[0])) {
123
+ $this->readBytes[$type] += strlen($data);
124
  $read[$type] = $data;
125
  }
126
+ if ($close) {
127
+ fclose($fileHandle);
 
128
  unset($this->fileHandles[$type]);
129
  }
130
  }
137
  */
138
  public function areOpen()
139
  {
140
+ return $this->pipes && $this->fileHandles;
141
  }
142
 
143
  /**
177
  }
178
  $this->files = array();
179
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  }
vendor/symfony/process/Process.php CHANGED
@@ -360,8 +360,7 @@ class Process
360
  do {
361
  $this->checkTimeout();
362
  $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
363
- $close = '\\' !== DIRECTORY_SEPARATOR || !$running;
364
- $this->readPipes(true, $close);
365
  } while ($running);
366
 
367
  while ($this->isRunning()) {
@@ -463,13 +462,7 @@ class Process
463
  */
464
  public function getOutput()
465
  {
466
- if ($this->outputDisabled) {
467
- throw new LogicException('Output has been disabled.');
468
- }
469
-
470
- $this->requireProcessIsStarted(__FUNCTION__);
471
-
472
- $this->readPipes(false, '\\' === DIRECTORY_SEPARATOR ? !$this->processInformation['running'] : true);
473
 
474
  if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
475
  return '';
@@ -491,11 +484,7 @@ class Process
491
  */
492
  public function getIncrementalOutput()
493
  {
494
- if ($this->outputDisabled) {
495
- throw new LogicException('Output has been disabled.');
496
- }
497
-
498
- $this->requireProcessIsStarted(__FUNCTION__);
499
 
500
  $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
501
  $this->incrementalOutputOffset = ftell($this->stdout);
@@ -531,13 +520,7 @@ class Process
531
  */
532
  public function getErrorOutput()
533
  {
534
- if ($this->outputDisabled) {
535
- throw new LogicException('Output has been disabled.');
536
- }
537
-
538
- $this->requireProcessIsStarted(__FUNCTION__);
539
-
540
- $this->readPipes(false, '\\' === DIRECTORY_SEPARATOR ? !$this->processInformation['running'] : true);
541
 
542
  if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
543
  return '';
@@ -560,11 +543,7 @@ class Process
560
  */
561
  public function getIncrementalErrorOutput()
562
  {
563
- if ($this->outputDisabled) {
564
- throw new LogicException('Output has been disabled.');
565
- }
566
-
567
- $this->requireProcessIsStarted(__FUNCTION__);
568
 
569
  $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
570
  $this->incrementalErrorOutputOffset = ftell($this->stderr);
@@ -1295,14 +1274,15 @@ class Process
1295
  }
1296
 
1297
  $this->processInformation = proc_get_status($this->process);
 
1298
 
1299
- $this->readPipes($blocking, '\\' === DIRECTORY_SEPARATOR ? !$this->processInformation['running'] : true);
1300
 
1301
  if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
1302
  $this->processInformation = $this->fallbackStatus + $this->processInformation;
1303
  }
1304
 
1305
- if (!$this->processInformation['running']) {
1306
  $this->close();
1307
  }
1308
  }
@@ -1328,6 +1308,24 @@ class Process
1328
  return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
1329
  }
1330
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1331
  /**
1332
  * Validates and returns the filtered timeout.
1333
  *
360
  do {
361
  $this->checkTimeout();
362
  $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
363
+ $this->readPipes($running, '\\' !== DIRECTORY_SEPARATOR || !$running);
 
364
  } while ($running);
365
 
366
  while ($this->isRunning()) {
462
  */
463
  public function getOutput()
464
  {
465
+ $this->readPipesForOutput(__FUNCTION__);
 
 
 
 
 
 
466
 
467
  if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
468
  return '';
484
  */
485
  public function getIncrementalOutput()
486
  {
487
+ $this->readPipesForOutput(__FUNCTION__);
 
 
 
 
488
 
489
  $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
490
  $this->incrementalOutputOffset = ftell($this->stdout);
520
  */
521
  public function getErrorOutput()
522
  {
523
+ $this->readPipesForOutput(__FUNCTION__);
 
 
 
 
 
 
524
 
525
  if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
526
  return '';
543
  */
544
  public function getIncrementalErrorOutput()
545
  {
546
+ $this->readPipesForOutput(__FUNCTION__);
 
 
 
 
547
 
548
  $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
549
  $this->incrementalErrorOutputOffset = ftell($this->stderr);
1274
  }
1275
 
1276
  $this->processInformation = proc_get_status($this->process);
1277
+ $running = $this->processInformation['running'];
1278
 
1279
+ $this->readPipes($running && $blocking, '\\' !== DIRECTORY_SEPARATOR || !$running);
1280
 
1281
  if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
1282
  $this->processInformation = $this->fallbackStatus + $this->processInformation;
1283
  }
1284
 
1285
+ if (!$running) {
1286
  $this->close();
1287
  }
1288
  }
1308
  return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
1309
  }
1310
 
1311
+ /**
1312
+ * Reads pipes for the freshest output.
1313
+ *
1314
+ * @param $caller The name of the method that needs fresh outputs
1315
+ *
1316
+ * @throws LogicException in case output has been disabled or process is not started
1317
+ */
1318
+ private function readPipesForOutput($caller)
1319
+ {
1320
+ if ($this->outputDisabled) {
1321
+ throw new LogicException('Output has been disabled.');
1322
+ }
1323
+
1324
+ $this->requireProcessIsStarted($caller);
1325
+
1326
+ $this->updateStatus(false);
1327
+ }
1328
+
1329
  /**
1330
  * Validates and returns the filtered timeout.
1331
  *
vendor/symfony/process/ProcessBuilder.php CHANGED
File without changes
vendor/symfony/process/ProcessUtils.php CHANGED
File without changes
vendor/symfony/process/Tests/ExecutableFinderTest.php CHANGED
File without changes
vendor/symfony/process/Tests/NonStopableProcess.php CHANGED
File without changes
vendor/symfony/process/Tests/PhpExecutableFinderTest.php CHANGED
File without changes
vendor/symfony/process/Tests/PhpProcessTest.php CHANGED
File without changes
vendor/symfony/process/Tests/PipeStdinInStdoutStdErrStreamSelect.php CHANGED
File without changes
vendor/symfony/process/Tests/ProcessBuilderTest.php CHANGED
File without changes
vendor/symfony/process/Tests/ProcessFailedExceptionTest.php CHANGED
File without changes
vendor/symfony/process/Tests/ProcessTest.php CHANGED
@@ -31,7 +31,7 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
31
  public static function setUpBeforeClass()
32
  {
33
  $phpBin = new PhpExecutableFinder();
34
- self::$phpBin = 'phpdbg' === PHP_SAPI ? 'php' : $phpBin->find();
35
  if ('\\' !== DIRECTORY_SEPARATOR) {
36
  // exec is mandatory to deal with sending a signal to the process
37
  // see https://github.com/symfony/symfony/issues/5030 about prepending
@@ -192,9 +192,6 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
192
  */
193
  public function testSetStreamAsInput($code, $size)
194
  {
195
- if ('\\' === DIRECTORY_SEPARATOR) {
196
- $this->markTestIncomplete('This test fails with a timeout on Windows, can someone investigate please?');
197
- }
198
  $expected = str_repeat(str_repeat('*', 1024), $size).'!';
199
  $expectedLength = (1024 * $size) + 1;
200
 
@@ -791,10 +788,7 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
791
 
792
  public function testIdleTimeoutNotExceededWhenOutputIsSent()
793
  {
794
- if ('\\' === DIRECTORY_SEPARATOR) {
795
- $this->markTestIncomplete('This test fails with a timeout on Windows, can someone investigate please?');
796
- }
797
- $process = $this->getProcess(sprintf('%s -r %s', self::$phpBin, escapeshellarg('while (true) {echo "foo\n"; usleep(10000);}')));
798
  $process->setTimeout(1);
799
  $process->start();
800
 
@@ -802,15 +796,15 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
802
  usleep(1000);
803
  }
804
 
805
- $process->setIdleTimeout(0.1);
806
 
807
  try {
808
  $process->wait();
809
  $this->fail('A timeout exception was expected.');
810
- } catch (ProcessTimedOutException $ex) {
811
- $this->assertTrue($ex->isGeneralTimeout(), 'A general timeout is expected.');
812
- $this->assertFalse($ex->isIdleTimeout(), 'No idle timeout is expected.');
813
- $this->assertEquals(1, $ex->getExceededTimeout());
814
  }
815
  }
816
 
@@ -1165,6 +1159,31 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
1165
  return $codes;
1166
  }
1167
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1168
  /**
1169
  * provides default method names for simple getter/setter.
1170
  */
31
  public static function setUpBeforeClass()
32
  {
33
  $phpBin = new PhpExecutableFinder();
34
+ self::$phpBin = getenv('SYMFONY_PROCESS_PHP_TEST_BINARY') ?: ('phpdbg' === PHP_SAPI ? 'php' : $phpBin->find());
35
  if ('\\' !== DIRECTORY_SEPARATOR) {
36
  // exec is mandatory to deal with sending a signal to the process
37
  // see https://github.com/symfony/symfony/issues/5030 about prepending
192
  */
193
  public function testSetStreamAsInput($code, $size)
194
  {
 
 
 
195
  $expected = str_repeat(str_repeat('*', 1024), $size).'!';
196
  $expectedLength = (1024 * $size) + 1;
197
 
788
 
789
  public function testIdleTimeoutNotExceededWhenOutputIsSent()
790
  {
791
+ $process = $this->getProcess(sprintf('%s -r %s', self::$phpBin, escapeshellarg('while (true) {echo \'foo \'; usleep(1000);}')));
 
 
 
792
  $process->setTimeout(1);
793
  $process->start();
794
 
796
  usleep(1000);
797
  }
798
 
799
+ $process->setIdleTimeout(0.5);
800
 
801
  try {
802
  $process->wait();
803
  $this->fail('A timeout exception was expected.');
804
+ } catch (ProcessTimedOutException $e) {
805
+ $this->assertTrue($e->isGeneralTimeout(), 'A general timeout is expected.');
806
+ $this->assertFalse($e->isIdleTimeout(), 'No idle timeout is expected.');
807
+ $this->assertEquals(1, $e->getExceededTimeout());
808
  }
809
  }
810
 
1159
  return $codes;
1160
  }
1161
 
1162
+ /**
1163
+ * @dataProvider provideVariousIncrementals
1164
+ */
1165
+ public function testIncrementalOutputDoesNotRequireAnotherCall($stream, $method) {
1166
+ $process = new Process(self::$phpBin.' -r '.escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\''.$stream.'\', $n, 1); $n++; usleep(1000); }'), null, null, null, null);
1167
+ $process->start();
1168
+ $result = '';
1169
+ $limit = microtime(true) + 3;
1170
+ $expected = '012';
1171
+
1172
+ while ($result !== $expected && microtime(true) < $limit) {
1173
+ $result .= $process->$method();
1174
+ }
1175
+
1176
+ $this->assertSame($expected, $result);
1177
+ $process->stop();
1178
+ }
1179
+
1180
+ public function provideVariousIncrementals() {
1181
+ return array(
1182
+ array('php://stdout', 'getIncrementalOutput'),
1183
+ array('php://stderr', 'getIncrementalErrorOutput'),
1184
+ );
1185
+ }
1186
+
1187
  /**
1188
  * provides default method names for simple getter/setter.
1189
  */
vendor/symfony/process/Tests/ProcessUtilsTest.php CHANGED
File without changes
vendor/symfony/process/Tests/SignalListener.php CHANGED
File without changes
vendor/symfony/process/composer.json CHANGED
File without changes
vendor/symfony/process/phpunit.xml.dist CHANGED
File without changes