Total Upkeep – WordPress Backup Plugin plus Restore & Migrate by BoldGrid - Version 1.7.0

Version Description

Release date: Dec 4th, 2018

  • New feature: Added auto-update settings for individual plugins and themes.
  • New feature: Added limited-lifetime download links for archive files.
  • New feature: Added import backup archive from URL address.
  • New feature: Added progress bar to show status of backups.
  • New feature: Adding the ability to set and title and description to a backup.
  • New feature: Adding the ability to flag a backup as being proteced (excluded from retention).
  • Update: Update protection is now valid for 1 hour after a full backup from the WordPress Updates or Plugins page.
  • Update: Made the Backup Archives page the default page in the admin menu.
  • Bug fix: Set a default backup directory if path in settings is not valid. Remove filters before fixing home and siteurl on restore.
  • Bug fix: Some HTML was caught in translations.
  • Bug fix: Duplicate emails were sent when a backup was complete, fixed.
  • Bug fix: Preserve timestamp on ftp / sftp uploads.
  • Bug fix: Fixed CLI support detection on some EA4 servers.
  • Update: Save settings and reload to the current section.
  • Update: Reorganized settings sections.
Download this release

Release Info

Developer boldgrid
Plugin Icon 128x128 Total Upkeep – WordPress Backup Plugin plus Restore & Migrate by BoldGrid
Version 1.7.0
Comparing to
See all releases

Code changes from version 1.6.6 to 1.7.0

Files changed (136) hide show
  1. admin/class-boldgrid-backup-admin-archive-actions.php +93 -0
  2. admin/class-boldgrid-backup-admin-archive-details.php +33 -1
  3. admin/class-boldgrid-backup-admin-archive-log.php +15 -5
  4. admin/class-boldgrid-backup-admin-archive.php +118 -7
  5. admin/class-boldgrid-backup-admin-archives.php +23 -7
  6. admin/class-boldgrid-backup-admin-auto-rollback.php +47 -5
  7. admin/class-boldgrid-backup-admin-backup-dir.php +48 -2
  8. admin/class-boldgrid-backup-admin-config.php +9 -4
  9. admin/class-boldgrid-backup-admin-core.php +95 -56
  10. admin/class-boldgrid-backup-admin-db-dump.php +8 -0
  11. admin/class-boldgrid-backup-admin-email.php +1 -1
  12. admin/class-boldgrid-backup-admin-go-pro.php +19 -2
  13. admin/class-boldgrid-backup-admin-in-progress-data.php +123 -0
  14. admin/class-boldgrid-backup-admin-in-progress.php +64 -9
  15. admin/class-boldgrid-backup-admin-notice.php +19 -0
  16. admin/class-boldgrid-backup-admin-remote.php +4 -10
  17. admin/class-boldgrid-backup-admin-settings.php +78 -142
  18. admin/class-boldgrid-backup-admin-support.php +82 -0
  19. admin/class-boldgrid-backup-admin-test.php +77 -55
  20. admin/class-boldgrid-backup-admin-upload.php +144 -18
  21. admin/class-boldgrid-backup-admin-utility.php +19 -0
  22. admin/class-boldgrid-backup-admin-xhprof.php +6 -3
  23. admin/class-boldgrid-backup-admin.php +19 -0
  24. admin/compressor/class-boldgrid-backup-admin-compressor-php-zip.php +54 -2
  25. admin/css/boldgrid-backup-admin-home.css +4 -0
  26. admin/css/boldgrid-backup-admin-settings.css +5 -1
  27. admin/css/boldgrid-backup-admin.css +127 -3
  28. admin/js/boldgrid-backup-admin-archive-actions.js +97 -0
  29. admin/js/boldgrid-backup-admin-archive-details.js +75 -1
  30. admin/js/boldgrid-backup-admin-backup-now.js +7 -1
  31. admin/js/boldgrid-backup-admin-ftp-settings.js +15 -7
  32. admin/js/boldgrid-backup-admin-home.js +98 -0
  33. admin/js/boldgrid-backup-admin-in-progress.js +446 -0
  34. admin/js/boldgrid-backup-admin-settings-autoupdate.js +195 -0
  35. admin/js/boldgrid-backup-admin-settings.js +0 -27
  36. admin/js/boldgrid-backup-admin-update-selectors.js +4 -1
  37. admin/js/boldgrid-backup-admin.js +0 -63
  38. admin/partials/archives/add-new.php +13 -3
  39. admin/partials/backup-now-modal/title.php +28 -0
  40. admin/partials/boldgrid-backup-admin-archive-details.php +80 -28
  41. admin/partials/boldgrid-backup-admin-backup-button.php +5 -2
  42. admin/partials/boldgrid-backup-admin-backup-modal.php +4 -1
  43. admin/partials/boldgrid-backup-admin-home.php +9 -4
  44. admin/partials/boldgrid-backup-admin-settings.php +35 -26
  45. admin/partials/boldgrid-backup-admin-test.php +10 -0
  46. admin/partials/remote/ftp.php +1 -8
  47. admin/partials/remote/local.php +33 -0
  48. admin/partials/settings/auto-backup.php +69 -0
  49. admin/partials/settings/auto-rollback.php +62 -0
  50. admin/partials/settings/auto-updates.php +0 -192
  51. admin/partials/settings/backup-directory.php +17 -18
  52. admin/partials/settings/connect-key.php +7 -58
  53. admin/partials/settings/retention.php +18 -32
  54. admin/partials/settings/scheduler.php +9 -7
  55. admin/partials/settings/storage.php +9 -10
  56. admin/partials/tools/local-remote.php +2 -1
  57. admin/remote/class-boldgrid-backup-admin-ftp-hooks.php +15 -7
  58. admin/remote/class-boldgrid-backup-admin-ftp-page.php +54 -25
  59. admin/remote/class-boldgrid-backup-admin-ftp.php +83 -10
  60. admin/storage/class-boldgrid-backup-admin-storage-local.php +210 -0
  61. boldgrid-backup.php +14 -33
  62. build/clipboard.min.js +7 -0
  63. cron/cli-support.php +8 -4
  64. includes/class-boldgrid-backup-activator.php +15 -13
  65. includes/class-boldgrid-backup-authentication.php +80 -0
  66. includes/class-boldgrid-backup-download.php +67 -0
  67. includes/class-boldgrid-backup-file.php +70 -0
  68. includes/class-boldgrid-backup.php +33 -2
  69. includes/config/config.plugin.php +4 -12
  70. includes/config/config.sample.php +3 -3
  71. readme.txt +24 -9
  72. vendor/autoload.php +1 -1
  73. vendor/boldgrid/library/.gitignore +1 -0
  74. vendor/boldgrid/library/.travis.yml +22 -54
  75. vendor/boldgrid/library/README.md +59 -0
  76. vendor/boldgrid/library/composer.json +5 -0
  77. vendor/boldgrid/library/gulpfile.js +8 -0
  78. vendor/boldgrid/library/package-lock.json +0 -1907
  79. vendor/boldgrid/library/package.json +5 -2
  80. vendor/boldgrid/library/src/Library/Api/Call.php +1 -1
  81. vendor/boldgrid/library/src/Library/Editor.php +42 -0
  82. vendor/boldgrid/library/src/Library/License.php +26 -10
  83. vendor/boldgrid/library/src/Library/Menu/External.php +5 -5
  84. vendor/boldgrid/library/src/Library/Menu/Reseller.php +5 -5
  85. vendor/boldgrid/library/src/Library/Notice.php +10 -1
  86. vendor/boldgrid/library/src/Library/Notice/KeyPrompt.php +17 -2
  87. vendor/boldgrid/library/src/Library/Page/Connect.php +158 -6
  88. vendor/boldgrid/library/src/Library/Plugin/Checker.php +3 -3
  89. vendor/boldgrid/library/src/Library/ReleaseChannel.php +33 -28
  90. vendor/boldgrid/library/src/Library/Start.php +1 -0
  91. vendor/boldgrid/library/src/Library/Ui.php +15 -1
  92. vendor/boldgrid/library/src/Library/Update.php +144 -4
  93. vendor/boldgrid/library/src/Library/Views/Connect.php +69 -3
  94. vendor/boldgrid/library/src/Library/Views/Connect/AutoUpdates.php +358 -0
  95. vendor/boldgrid/library/src/Library/Views/Connect/ConnectKey.php +15 -0
  96. vendor/boldgrid/library/src/Library/Views/Connect/UpdateChannels.php +165 -0
  97. vendor/boldgrid/library/src/Library/Views/EnvatoFreeKey.php +3 -3
  98. vendor/boldgrid/library/src/Library/Views/KeyPrompt.php +23 -23
  99. vendor/boldgrid/library/src/Library/Views/KeyPromptMini.php +73 -0
  100. vendor/boldgrid/library/src/Util/Load.php +17 -0
  101. vendor/boldgrid/library/src/Util/Option.php +4 -5
  102. vendor/boldgrid/library/src/Util/Version.php +9 -2
  103. vendor/boldgrid/library/src/assets/css/admin.css +131 -1
  104. vendor/boldgrid/library/src/assets/css/api-notice.css +34 -0
  105. vendor/boldgrid/library/src/assets/css/attributes.css +39 -0
  106. vendor/boldgrid/library/src/assets/css/ui.css +4 -0
  107. vendor/boldgrid/library/src/assets/fonts/boldgrid.eot +0 -0
  108. vendor/boldgrid/library/src/assets/fonts/boldgrid.svg +5 -4
  109. vendor/boldgrid/library/src/assets/fonts/boldgrid.ttf +0 -0
  110. vendor/boldgrid/library/src/assets/fonts/boldgrid.woff +0 -0
  111. vendor/boldgrid/library/src/assets/js/api-notice.js +108 -68
  112. vendor/boldgrid/library/src/assets/js/attributes.js +255 -0
  113. vendor/boldgrid/library/src/assets/js/connect.js +111 -4
  114. vendor/boldgrid/library/src/assets/js/license.js +6 -8
  115. vendor/boldgrid/library/src/assets/js/notice.js +4 -5
  116. vendor/boldgrid/library/src/assets/js/sticky.js +306 -276
  117. vendor/boldgrid/library/src/assets/js/ui.js +24 -4
  118. vendor/boldgrid/library/yarn.lock +2112 -153
  119. vendor/cbschuld/browser.php +1 -1
  120. vendor/composer/ClassLoader.php +1 -1
  121. vendor/composer/autoload_classmap.php +44 -0
  122. vendor/composer/autoload_real.php +7 -7
  123. vendor/composer/autoload_static.php +51 -3
  124. vendor/composer/installed.json +16 -16
  125. vendor/phpseclib/phpseclib/README.md +1 -1
  126. vendor/phpseclib/phpseclib/appveyor.yml +27 -0
  127. vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php +3 -3
  128. vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php +78 -20
  129. vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +5 -4
  130. vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php +12 -0
  131. vendor/phpseclib/phpseclib/phpseclib/File/X509.php +10 -2
  132. vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php +0 -1
  133. vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php +11 -1
  134. vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php +175 -19
  135. vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php +2 -0
  136. vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php +12 -0
admin/class-boldgrid-backup-admin-archive-actions.php CHANGED
@@ -58,7 +58,18 @@ class Boldgrid_Backup_Admin_Archive_Actions {
58
  'boldgrid-backup'
59
  );
60
 
 
 
 
 
 
 
 
 
 
 
61
  $handle = 'boldgrid-backup-admin-archive-actions';
 
62
  wp_register_script(
63
  $handle,
64
  plugin_dir_url( __FILE__ ) . 'js/' . $handle . '.js',
@@ -66,14 +77,32 @@ class Boldgrid_Backup_Admin_Archive_Actions {
66
  BOLDGRID_BACKUP_VERSION,
67
  false
68
  );
 
69
  $translation = array(
70
  'accessType' => $access_type,
71
  'archiveNonce' => $archive_nonce,
72
  'deleteConfirmText' => $delete_confirm_text,
73
  'restoreConfirmText' => $restore_confirm_text,
 
 
 
 
 
 
74
  );
 
75
  wp_localize_script( $handle, 'BoldGridBackupAdminArchiveActions', $translation );
76
  wp_enqueue_script( $handle );
 
 
 
 
 
 
 
 
 
 
77
  }
78
 
79
  /**
@@ -190,4 +219,68 @@ class Boldgrid_Backup_Admin_Archive_Actions {
190
 
191
  return $button;
192
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  }
58
  'boldgrid-backup'
59
  );
60
 
61
+ $link_error_text = __( 'Could not generate link.', 'boldgrid-backup' );
62
+ $unknown_error_text = __( 'Unknown error.', 'boldgrid-backup' );
63
+ $copy_text = __( 'Copy Link', 'boldgrid-backup' );
64
+ $copied_text = __( 'Copied!', 'boldgrid-backup' );
65
+ $expires_text = __( 'This link expires in:', 'boldgrid-backup' );
66
+ $link_disclaimer_text = __(
67
+ 'Please keep this link private, as the download file contains sensitive data.',
68
+ 'boldgrid-backup'
69
+ );
70
+
71
  $handle = 'boldgrid-backup-admin-archive-actions';
72
+
73
  wp_register_script(
74
  $handle,
75
  plugin_dir_url( __FILE__ ) . 'js/' . $handle . '.js',
77
  BOLDGRID_BACKUP_VERSION,
78
  false
79
  );
80
+
81
  $translation = array(
82
  'accessType' => $access_type,
83
  'archiveNonce' => $archive_nonce,
84
  'deleteConfirmText' => $delete_confirm_text,
85
  'restoreConfirmText' => $restore_confirm_text,
86
+ 'linkErrorText' => $link_error_text,
87
+ 'unknownErrorText' => $unknown_error_text,
88
+ 'copyText' => $copy_text,
89
+ 'copiedText' => $copied_text,
90
+ 'expiresText' => $expires_text,
91
+ 'linkDisclaimerText' => $link_disclaimer_text,
92
  );
93
+
94
  wp_localize_script( $handle, 'BoldGridBackupAdminArchiveActions', $translation );
95
  wp_enqueue_script( $handle );
96
+
97
+ // Enqueue the external clipboard script.
98
+ wp_enqueue_script(
99
+ 'clipboard',
100
+ plugin_dir_url( BOLDGRID_BACKUP_PATH . '/boldgrid-backup.php' ) .
101
+ '/build/clipboard.min.js',
102
+ array( 'jquery' ),
103
+ '2.0.1',
104
+ true
105
+ );
106
  }
107
 
108
  /**
219
 
220
  return $button;
221
  }
222
+
223
+ /**
224
+ * Return a button link to request to generate a public link to download an archive file.
225
+ *
226
+ * @since 1.7.0
227
+ *
228
+ * @param string $filename Filename.
229
+ * @return string
230
+ */
231
+ public function get_download_link_button( $filename ) {
232
+ $link = '';
233
+ $archive = $this->core->archive->get_by_name( $filename );
234
+
235
+ if ( ! empty( $archive ) ) {
236
+ $link = sprintf(
237
+ '<a
238
+ id="download-link-button"
239
+ class="button"
240
+ href="#"
241
+ data-filename="%1$s"
242
+ data-nonce="%2$s"
243
+ >
244
+ %3$s
245
+ </a>
246
+ <span class="spinner"></span>
247
+ ',
248
+ /* 1 */ $archive['filename'],
249
+ /* 2 */ wp_create_nonce( 'boldgrid_backup_download_link' ),
250
+ /* 3 */ __( 'Get Download Link', 'boldgrid-backup' )
251
+ );
252
+ }
253
+
254
+ return $link;
255
+ }
256
+
257
+ /**
258
+ * Callback function for generating a public link to download an archive file.
259
+ *
260
+ * Used on the backup archive details page. The link is only valid for a limited time, which
261
+ * is configurable in a configuration file.
262
+ *
263
+ * @since 1.7.0
264
+ *
265
+ * @see Boldgrid_Backup_Admin_Archive::generate_download_link()
266
+ *
267
+ * @uses $_POST['archive_filename'] Backup archive filename.
268
+ *
269
+ * @return string
270
+ */
271
+ public function wp_ajax_generate_download_link() {
272
+ $archive_filename = ! empty( $_POST['archive_filename'] ) ?
273
+ sanitize_file_name( $_POST['archive_filename'] ) : null;
274
+
275
+ if ( check_admin_referer( 'boldgrid_backup_download_link', 'archive_auth' ) &&
276
+ current_user_can( 'update_plugins' ) && $archive_filename ) {
277
+ wp_send_json_success(
278
+ $this->core->archive->generate_download_link(
279
+ $archive_filename
280
+ )
281
+ );
282
+ } else {
283
+ wp_send_json_error();
284
+ }
285
+ }
286
  }
admin/class-boldgrid-backup-admin-archive-details.php CHANGED
@@ -110,6 +110,9 @@ class Boldgrid_Backup_Admin_Archive_Details {
110
 
111
  wp_enqueue_style( 'bglib-ui-css' );
112
 
 
 
 
113
  /**
114
  * Allow other plugins to enqueue scripts on this page.
115
  *
@@ -149,12 +152,14 @@ class Boldgrid_Backup_Admin_Archive_Details {
149
  } else {
150
  $archive = array(
151
  'filename' => $filename,
152
- 'filepath' => $this->core->backup_dir->get_path_to( $archive['filename'] ),
153
  );
154
  }
155
 
156
  // Initialize the archive. We will need it in our included template below.
157
  $this->core->archive->init( $archive['filepath'] );
 
 
158
 
159
  include BOLDGRID_BACKUP_PATH . '/admin/partials/boldgrid-backup-admin-archive-details.php';
160
  }
@@ -174,4 +179,31 @@ class Boldgrid_Backup_Admin_Archive_Details {
174
  public function validate_nonce() {
175
  return check_ajax_referer( 'boldgrid_backup_remote_storage_upload', 'security', false );
176
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  }
110
 
111
  wp_enqueue_style( 'bglib-ui-css' );
112
 
113
+ wp_enqueue_script( 'bglib-attributes-js' );
114
+ wp_enqueue_style( 'bglib-attributes-css' );
115
+
116
  /**
117
  * Allow other plugins to enqueue scripts on this page.
118
  *
152
  } else {
153
  $archive = array(
154
  'filename' => $filename,
155
+ 'filepath' => $this->core->backup_dir->get_path_to( $filename ),
156
  );
157
  }
158
 
159
  // Initialize the archive. We will need it in our included template below.
160
  $this->core->archive->init( $archive['filepath'] );
161
+ $title = $this->core->archive->get_attribute( 'title' );
162
+ $description = $this->core->archive->get_attribute( 'description' );
163
 
164
  include BOLDGRID_BACKUP_PATH . '/admin/partials/boldgrid-backup-admin-archive-details.php';
165
  }
179
  public function validate_nonce() {
180
  return check_ajax_referer( 'boldgrid_backup_remote_storage_upload', 'security', false );
181
  }
182
+
183
+ /**
184
+ * Handle the ajax request to "Update" from a backup archive page.
185
+ *
186
+ * @since 1.7.0
187
+ */
188
+ public function wp_ajax_update() {
189
+ if ( ! $this->validate_nonce() ) {
190
+ wp_send_json_error( __( 'Permission denied.', 'boldgrid-backup' ) );
191
+ }
192
+
193
+ $filename = ! empty( $_POST['filename'] ) ? sanitize_file_name( $_POST['filename'] ) : false; // phpcs:ignore WordPress.CSRF.NonceVerification
194
+ $filepath = $this->core->backup_dir->get_path_to( $filename );
195
+ if ( empty( $filename ) || ! $this->core->wp_filesystem->exists( $filepath ) ) {
196
+ wp_send_json_error( __( 'Invalid archive filepath.', 'boldgrid-backup' ) );
197
+ }
198
+
199
+ $this->core->archive->init( $filepath );
200
+
201
+ if ( ! empty( $_POST['attributes'] ) ) { // phpcs:ignore WordPress.CSRF.NonceVerification
202
+ foreach ( $_POST['attributes'] as $key => $value ) { // phpcs:ignore WordPress.CSRF.NonceVerification
203
+ $this->core->archive->set_attribute( $key, stripslashes( $value ) );
204
+ }
205
+ }
206
+
207
+ wp_send_json_success();
208
+ }
209
  }
admin/class-boldgrid-backup-admin-archive-log.php CHANGED
@@ -129,16 +129,19 @@ class Boldgrid_Backup_Admin_Archive_Log {
129
  *
130
  * @since 1.6.0
131
  *
132
- * @param string $filepath Archive file path.
 
133
  */
134
- public function restore_by_zip( $filepath ) {
135
  $log_filepath = $this->path_from_zip( $filepath );
136
- $log_filename = basename( $log_filepath );
137
 
138
  if ( $this->core->wp_filesystem->exists( $log_filepath ) ) {
139
  return true;
140
  }
141
 
 
 
 
142
  // Extract the log file to ABSPATH.
143
  $zip = new Boldgrid_Backup_Admin_Compressor_Pcl_Zip( $this->core );
144
  $status = $zip->extract_one( $filepath, $log_filename );
@@ -148,8 +151,9 @@ class Boldgrid_Backup_Admin_Archive_Log {
148
 
149
  // Move the log file from the ABSPATH to the backup dir.
150
  $old_path = ABSPATH . $log_filename;
151
- $new_path = $this->core->backup_dir->get_path_to( $log_filename );
152
- return $this->core->wp_filesystem->move( $old_path, $new_path );
 
153
  }
154
 
155
  /**
@@ -178,6 +182,9 @@ class Boldgrid_Backup_Admin_Archive_Log {
178
  }
179
 
180
  // Add the log file to the archive file, as of 1.5.4.
 
 
 
181
  $archive = new PclZip( $info['filepath'] );
182
  if ( 0 === $archive ) {
183
  return false;
@@ -194,6 +201,9 @@ class Boldgrid_Backup_Admin_Archive_Log {
194
  return false;
195
  }
196
 
 
 
 
197
  return true;
198
  }
199
  }
129
  *
130
  * @since 1.6.0
131
  *
132
+ * @param string $filepath Archive file path.
133
+ * @param string $alt_log_filename Optional log file path. Default is to get from filepath.
134
  */
135
+ public function restore_by_zip( $filepath, $alt_log_filename = null ) {
136
  $log_filepath = $this->path_from_zip( $filepath );
 
137
 
138
  if ( $this->core->wp_filesystem->exists( $log_filepath ) ) {
139
  return true;
140
  }
141
 
142
+ $log_filename = ! empty( $alt_log_filename ) ?
143
+ $alt_log_filename : basename( $log_filepath );
144
+
145
  // Extract the log file to ABSPATH.
146
  $zip = new Boldgrid_Backup_Admin_Compressor_Pcl_Zip( $this->core );
147
  $status = $zip->extract_one( $filepath, $log_filename );
151
 
152
  // Move the log file from the ABSPATH to the backup dir.
153
  $old_path = ABSPATH . $log_filename;
154
+ $new_path = $this->core->backup_dir->get_path_to( basename( $log_filepath ) );
155
+
156
+ return $this->core->wp_filesystem->move( $old_path, $new_path, true );
157
  }
158
 
159
  /**
182
  }
183
 
184
  // Add the log file to the archive file, as of 1.5.4.
185
+ if ( ! class_exists( 'PclZip' ) ) {
186
+ require_once ABSPATH . 'wp-admin/includes/class-pclzip.php';
187
+ }
188
  $archive = new PclZip( $info['filepath'] );
189
  if ( 0 === $archive ) {
190
  return false;
201
  return false;
202
  }
203
 
204
+ // Ensure the act updating the log file does not change the backup file's timestamp.
205
+ $this->core->wp_filesystem->touch( $info['filepath'], $info['lastmodunix'] );
206
+
207
  return true;
208
  }
209
  }
admin/class-boldgrid-backup-admin-archive.php CHANGED
@@ -121,6 +121,18 @@ class Boldgrid_Backup_Admin_Archive {
121
  return $deleted;
122
  }
123
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  /**
125
  * Get an archive by name.
126
  *
@@ -190,7 +202,6 @@ class Boldgrid_Backup_Admin_Archive {
190
  * @param string $filepath File path.
191
  */
192
  public function init( $filepath ) {
193
-
194
  $filepath = strip_tags( $filepath );
195
 
196
  if ( ! empty( $this->filepath ) && $filepath === $this->filepath ) {
@@ -199,8 +210,6 @@ class Boldgrid_Backup_Admin_Archive {
199
 
200
  $this->reset();
201
 
202
- $zip = new Boldgrid_Backup_Admin_Compressor_Pcl_Zip( $this->core );
203
-
204
  $this->filepath = $filepath;
205
  $this->filename = basename( $this->filepath );
206
 
@@ -213,7 +222,6 @@ class Boldgrid_Backup_Admin_Archive {
213
  $have_log = $this->core->archive_log->restore_by_zip( $this->filepath );
214
  }
215
 
216
- // Init our log.
217
  if ( $have_log ) {
218
  $this->log = $this->core->archive_log->get_by_zip( $this->filepath );
219
  }
@@ -227,8 +235,6 @@ class Boldgrid_Backup_Admin_Archive {
227
  $this->compressor = ! empty( $this->log['compressor'] ) ? $this->log['compressor'] : 'php_zip';
228
 
229
  $this->view_details_url = admin_url( 'admin.php?page=boldgrid-backup-archive-details&filename=' . $this->filename );
230
-
231
- unset( $zip );
232
  }
233
 
234
  /**
@@ -337,6 +343,21 @@ class Boldgrid_Backup_Admin_Archive {
337
  $this->compressor = null;
338
  }
339
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  /**
341
  * Update an archive's timestamp based on the time in the log.
342
  *
@@ -347,7 +368,6 @@ class Boldgrid_Backup_Admin_Archive {
347
  * timestamp from the log and configure the last modified appropriately.
348
  */
349
  public function update_timestamp() {
350
-
351
  // If we don't have what we need, abort.
352
  if ( empty( $this->filepath ) || empty( $this->log['lastmodunix'] ) ) {
353
  return false;
@@ -355,4 +375,95 @@ class Boldgrid_Backup_Admin_Archive {
355
 
356
  return $this->core->wp_filesystem->touch( $this->filepath, $this->log['lastmodunix'] );
357
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
  }
121
  return $deleted;
122
  }
123
 
124
+ /**
125
+ * Get an attribute from the log.
126
+ *
127
+ * @since 1.7.0
128
+ *
129
+ * @param string $key Attributes are key / value pairs.
130
+ * @return mixed
131
+ */
132
+ public function get_attribute( $key ) {
133
+ return ! empty( $this->log[ $key ] ) ? $this->log[ $key ] : null;
134
+ }
135
+
136
  /**
137
  * Get an archive by name.
138
  *
202
  * @param string $filepath File path.
203
  */
204
  public function init( $filepath ) {
 
205
  $filepath = strip_tags( $filepath );
206
 
207
  if ( ! empty( $this->filepath ) && $filepath === $this->filepath ) {
210
 
211
  $this->reset();
212
 
 
 
213
  $this->filepath = $filepath;
214
  $this->filename = basename( $this->filepath );
215
 
222
  $have_log = $this->core->archive_log->restore_by_zip( $this->filepath );
223
  }
224
 
 
225
  if ( $have_log ) {
226
  $this->log = $this->core->archive_log->get_by_zip( $this->filepath );
227
  }
235
  $this->compressor = ! empty( $this->log['compressor'] ) ? $this->log['compressor'] : 'php_zip';
236
 
237
  $this->view_details_url = admin_url( 'admin.php?page=boldgrid-backup-archive-details&filename=' . $this->filename );
 
 
238
  }
239
 
240
  /**
343
  $this->compressor = null;
344
  }
345
 
346
+ /**
347
+ * Set an attribute in the log.
348
+ *
349
+ * @since 1.7.0
350
+ *
351
+ * @param string $key The key.
352
+ * @param string $value The value.
353
+ * @return bool
354
+ */
355
+ public function set_attribute( $key, $value ) {
356
+ $this->log[ $key ] = $value;
357
+
358
+ return $this->core->archive_log->write( $this->log );
359
+ }
360
+
361
  /**
362
  * Update an archive's timestamp based on the time in the log.
363
  *
368
  * timestamp from the log and configure the last modified appropriately.
369
  */
370
  public function update_timestamp() {
 
371
  // If we don't have what we need, abort.
372
  if ( empty( $this->filepath ) || empty( $this->log['lastmodunix'] ) ) {
373
  return false;
375
 
376
  return $this->core->wp_filesystem->touch( $this->filepath, $this->log['lastmodunix'] );
377
  }
378
+
379
+ /**
380
+ * Validate a download link request.
381
+ *
382
+ * @since 1.7.0
383
+ *
384
+ * @see Boldgrid_Backup_Admin_Archive::get_by_name()
385
+ *
386
+ * @param string $filename
387
+ * @return array
388
+ */
389
+ public function validate_link_request( $filename ) {
390
+ $result['is_valid'] = true;
391
+
392
+ // Verify access permissions.
393
+ if ( ! current_user_can( 'update_plugins' ) ) {
394
+ $result['errors'][] = __( 'Insufficient permission', 'boldgrid-backup' );
395
+ }
396
+
397
+ // Validate archive filename.
398
+ if ( empty( $filename ) ) {
399
+ $result['errors'][] = __( 'Invalid archive filename', 'boldgrid-backup' );
400
+ }
401
+
402
+ // Check WP_Filesystem method; ensure it is "direct".
403
+ if ( 'direct' !== get_filesystem_method() ) {
404
+ $result['errors'][] = __(
405
+ 'Filesystem access method is not "direct"',
406
+ 'boldgrid-backup'
407
+ );
408
+ }
409
+
410
+ // Get archive details.
411
+ $archive = $this->get_by_name( $filename );
412
+
413
+ // Check if archive file was found.
414
+ if ( empty( $archive ) ) {
415
+ $result['errors'][] = __( 'Archive file not found', 'boldgrid-backup' );
416
+ }
417
+
418
+ $expires = strtotime( '+' . $this->core->configs['public_link_lifetime'] );
419
+
420
+ if ( ! $expires || $expires < time() ) {
421
+ $result['errors'][] = __(
422
+ 'Invalid "public_link_lifetime" configuration setting',
423
+ 'boldgrid-backup'
424
+ );
425
+ }
426
+
427
+ if ( ! empty( $result['errors'] ) ) {
428
+ $result['is_valid'] = false;
429
+ }
430
+
431
+ return $result;
432
+ }
433
+
434
+ /**
435
+ * Generate a public link to download an archive file.
436
+ *
437
+ * The link is only valid for a limited time, which is configurable in a configuration file.
438
+ *
439
+ * @since 1.7.0
440
+ *
441
+ * @see Boldgrid_Backup_Admin_Archive::validate_link_request()
442
+ * @see Boldgrid_Backup_Authentication::create_token()
443
+ *
444
+ * @param string $filename
445
+ * @return string
446
+ */
447
+ public function generate_download_link( $filename ) {
448
+ $validation_results = $this->validate_link_request( $filename );
449
+
450
+ if ( $validation_results['is_valid'] ) {
451
+ $expires = strtotime( '+' . $this->core->configs['public_link_lifetime'] );
452
+ $token = Boldgrid_Backup_Authentication::create_token( $filename, $expires );
453
+
454
+ $response['download_url'] = get_site_url(
455
+ null,
456
+ 'wp-admin/admin-ajax.php?action=boldgrid_backup_download&t=' . $token
457
+ );
458
+
459
+ $response['expires_when'] = human_time_diff(
460
+ $expires,
461
+ current_time( 'timestamp', true )
462
+ );
463
+ } else {
464
+ $response['error'] = implode( '<br />', $validation_results['errors'] );
465
+ }
466
+
467
+ return $response;
468
+ }
469
  }
admin/class-boldgrid-backup-admin-archives.php CHANGED
@@ -103,11 +103,21 @@ class Boldgrid_Backup_Admin_Archives {
103
 
104
  $title_attr = ! empty( $location['title_attr'] ) ? sprintf( 'title="%1$s"', esc_attr( $location['title_attr'] ) ) : '';
105
 
 
 
 
 
 
 
 
 
 
106
  $locations[] = sprintf(
107
- '<span %2$s %3$s>%1$s</span>',
108
  esc_html( $location['title'] ),
109
  $data_attr,
110
- $title_attr
 
111
  );
112
  }
113
 
@@ -196,16 +206,21 @@ class Boldgrid_Backup_Admin_Archives {
196
  );
197
 
198
  foreach ( $this->core->archives_all->all as $archive ) {
199
- $locations = $this->get_locations( $archive );
200
-
201
- // dirlist -> lastmodunix -> mtime (last_modified in unix time).
202
  $this->core->time->init( $archive['last_modified'], 'utc' );
203
 
 
 
 
 
 
 
 
204
  $table .= sprintf(
205
  '
206
  <tr>
207
  <td>
208
  %2$s
 
209
  <p class="description">%6$s</p>
210
  </td>
211
  <td>
@@ -220,11 +235,12 @@ class Boldgrid_Backup_Admin_Archives {
220
  </tr>
221
  ',
222
  /* 1 */ $backup,
223
- /* 2 */ $this->core->time->get_span(),
224
  /* 3 */ Boldgrid_Backup_Admin_Utility::bytes_to_human( $archive['size'] ),
225
  /* 4 */ $archive['filename'],
226
  /* 5 */ $view_details,
227
- /* 6 */ $locations
 
228
  );
229
  }
230
  $table .= '</tbody>
103
 
104
  $title_attr = ! empty( $location['title_attr'] ) ? sprintf( 'title="%1$s"', esc_attr( $location['title_attr'] ) ) : '';
105
 
106
+ /*
107
+ * As of 1.7.0, the user can flag an archive as protected (exluded from retention
108
+ * process). Show a padlock next to those backups.
109
+ */
110
+ $icon = '';
111
+ if ( 'on_web_server' === $location_type && '1' === $this->core->archive->get_attribute( 'protect' ) ) {
112
+ $icon = '<span class="dashicons dashicons-lock" title="' . esc_attr__( 'This backup will not be deleted automatically from your Web Server due to your retention settings.', 'boldgrid-backup' ) . '"></span>';
113
+ }
114
+
115
  $locations[] = sprintf(
116
+ '<span %2$s %3$s>%1$s%4$s</span>',
117
  esc_html( $location['title'] ),
118
  $data_attr,
119
+ $title_attr,
120
+ $icon
121
  );
122
  }
123
 
206
  );
207
 
208
  foreach ( $this->core->archives_all->all as $archive ) {
 
 
 
209
  $this->core->time->init( $archive['last_modified'], 'utc' );
210
 
211
+ // Get the title of the backup.
212
+ $filepath = $this->core->backup_dir->get_path_to( $archive['filename'] );
213
+ $this->core->archive->init( $filepath );
214
+ $title = $this->core->archive->get_attribute( 'title' );
215
+
216
+ $locations = $this->get_locations( $archive );
217
+
218
  $table .= sprintf(
219
  '
220
  <tr>
221
  <td>
222
  %2$s
223
+ %7$s<br />
224
  <p class="description">%6$s</p>
225
  </td>
226
  <td>
235
  </tr>
236
  ',
237
  /* 1 */ $backup,
238
+ /* 2 */ empty( $title ) ? '' : '<strong>' . esc_html( $title ) . '</strong><br />',
239
  /* 3 */ Boldgrid_Backup_Admin_Utility::bytes_to_human( $archive['size'] ),
240
  /* 4 */ $archive['filename'],
241
  /* 5 */ $view_details,
242
+ /* 6 */ $locations,
243
+ /* 7 */ $this->core->time->get_span()
244
  );
245
  }
246
  $table .= '</tbody>
admin/class-boldgrid-backup-admin-auto-rollback.php CHANGED
@@ -223,6 +223,10 @@ class Boldgrid_Backup_Admin_Auto_Rollback {
223
  wp_localize_script( $handle, 'localizeScriptData', $localize_script_data );
224
 
225
  wp_enqueue_script( $handle );
 
 
 
 
226
  }
227
 
228
  /**
@@ -273,13 +277,28 @@ class Boldgrid_Backup_Admin_Auto_Rollback {
273
  * @since 1.6.0
274
  */
275
  public function enqueue_home_scripts() {
276
- wp_enqueue_script(
277
- 'boldgrid-backup-admin-home',
 
 
278
  plugin_dir_url( __FILE__ ) . 'js/boldgrid-backup-admin-home.js',
279
  array( 'jquery' ),
280
  BOLDGRID_BACKUP_VERSION,
281
  false
282
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  }
284
 
285
  /**
@@ -339,7 +358,7 @@ class Boldgrid_Backup_Admin_Auto_Rollback {
339
  * @since 1.6.0
340
  */
341
  public function enqueue_update_selectors() {
342
- if ( $this->on_update_page ) {
343
  $handle = 'boldgrid-backup-admin-update-selectors';
344
 
345
  wp_register_script(
@@ -757,9 +776,10 @@ class Boldgrid_Backup_Admin_Auto_Rollback {
757
  return;
758
  }
759
 
760
- // If there is a pending rollback, then abort.
761
  if ( ! empty( $pending_rollback['lastmodunix'] ) ) {
762
  $this->notice_activated_show();
 
763
  return;
764
  }
765
 
@@ -1027,7 +1047,7 @@ class Boldgrid_Backup_Admin_Auto_Rollback {
1027
  * @since 1.6.0
1028
  */
1029
  public function wp_ajax_get_protect_notice() {
1030
- if ( ! current_user_can( 'update_plugins' ) ) {
1031
  wp_send_json_error();
1032
  }
1033
 
@@ -1045,4 +1065,26 @@ class Boldgrid_Backup_Admin_Auto_Rollback {
1045
 
1046
  wp_send_json_success( $notice );
1047
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1048
  }
223
  wp_localize_script( $handle, 'localizeScriptData', $localize_script_data );
224
 
225
  wp_enqueue_script( $handle );
226
+
227
+ // Scripts required for showing backup in progress bar.
228
+ wp_enqueue_script( 'heartbeat' );
229
+ wp_enqueue_script( 'jquery-ui-progressbar' );
230
  }
231
 
232
  /**
277
  * @since 1.6.0
278
  */
279
  public function enqueue_home_scripts() {
280
+ $handle = 'boldgrid-backup-admin-home';
281
+
282
+ wp_register_script(
283
+ $handle,
284
  plugin_dir_url( __FILE__ ) . 'js/boldgrid-backup-admin-home.js',
285
  array( 'jquery' ),
286
  BOLDGRID_BACKUP_VERSION,
287
  false
288
  );
289
+
290
+ $translation = array(
291
+ 'savedTo' => __( 'File saved to: ', 'boldgrid-backup' ),
292
+ 'viewDetails' => __( 'View details', 'boldgrid-backup' ),
293
+ 'invalidUrl' => __( 'You must enter valid a URL address.', 'boldgrid-backup' ),
294
+ 'notZip' => __( 'The URL address is not a ZIP file.', 'boldgrid-backup' ),
295
+ 'unknownError' => __( 'Unknown error.', 'boldgrid-backup' ),
296
+ 'ajaxError' => __( 'Could not reach the URL address. HTTP error: ', 'boldgrid-backup' ),
297
+ 'urlRegex' => $this->core->configs['url_regex'],
298
+ );
299
+
300
+ wp_localize_script( $handle, 'BoldGridBackupAdminHome', $translation );
301
+ wp_enqueue_script( $handle );
302
  }
303
 
304
  /**
358
  * @since 1.6.0
359
  */
360
  public function enqueue_update_selectors() {
361
+ if ( $this->on_update_page || $this->core->utility->is_admin_page( 'boldgrid-backup' ) ) {
362
  $handle = 'boldgrid-backup-admin-update-selectors';
363
 
364
  wp_register_script(
776
  return;
777
  }
778
 
779
+ // If there is a pending rollback (backup within the last hour), then abort.
780
  if ( ! empty( $pending_rollback['lastmodunix'] ) ) {
781
  $this->notice_activated_show();
782
+
783
  return;
784
  }
785
 
1047
  * @since 1.6.0
1048
  */
1049
  public function wp_ajax_get_protect_notice() {
1050
+ if ( ! current_user_can( 'update_plugins' ) || ! $this->core->test->run_functionality_tests() ) {
1051
  wp_send_json_error();
1052
  }
1053
 
1065
 
1066
  wp_send_json_success( $notice );
1067
  }
1068
+
1069
+ /**
1070
+ * Validate the rollback option when retrieved.
1071
+ *
1072
+ * @since 1.7.0
1073
+ *
1074
+ * @param array|false WordPress option value for "boldgrid_backup_pending_rollback".
1075
+ * @param string Option name.
1076
+ * @return array|false
1077
+ */
1078
+ public function validate_rollback_option( $value, $option ) {
1079
+ $is_coutdown_active = ! empty( $value['deadline'] );
1080
+ $is_recent_backup = ! empty( $value['lastmodunix'] ) &&
1081
+ strtotime( '-1 HOUR' ) <= $value['lastmodunix'];
1082
+
1083
+ if ( ! $is_recent_backup && ! $is_coutdown_active ) {
1084
+ delete_site_option( $option );
1085
+ $value = false;
1086
+ }
1087
+
1088
+ return $value;
1089
+ }
1090
  }
admin/class-boldgrid-backup-admin-backup-dir.php CHANGED
@@ -168,6 +168,47 @@ class Boldgrid_Backup_Admin_Backup_Dir {
168
  return $backup_dir;
169
  }
170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  /**
172
  * Get and return the backup directory path.
173
  *
@@ -184,8 +225,10 @@ class Boldgrid_Backup_Admin_Backup_Dir {
184
 
185
  // If we have it in the settings, then use it.
186
  $settings = $this->core->settings->get_settings();
187
- if ( ! empty( $settings['backup_directory'] ) ) {
188
- $this->set( $settings['backup_directory'] );
 
 
189
  return $this->backup_directory;
190
  }
191
 
@@ -293,7 +336,10 @@ class Boldgrid_Backup_Admin_Backup_Dir {
293
 
294
  $this->set( $backup_directory );
295
 
 
 
296
  $settings['backup_directory'] = $backup_directory;
 
297
  $this->core->settings->save( $settings );
298
 
299
  return $this->backup_directory;
168
  return $backup_dir;
169
  }
170
 
171
+ /**
172
+ * Get a directory listing of our backup directory.
173
+ *
174
+ * @since 1.7.0
175
+ *
176
+ * @return array
177
+ */
178
+ public function dirlist() {
179
+ $this->get();
180
+
181
+ $files = array();
182
+
183
+ if ( $this->backup_directory ) {
184
+ $files = $this->core->wp_filesystem->dirlist( $this->backup_directory );
185
+ }
186
+
187
+ return $files;
188
+ }
189
+
190
+ /**
191
+ * Find files in backup directory where filename contains search string.
192
+ *
193
+ * @since 1.7.0
194
+ *
195
+ * @param string $search The search string / needle.
196
+ * @return array
197
+ */
198
+ public function dirlist_containing( $search ) {
199
+ $matches = array();
200
+ $dirlist = $this->dirlist();
201
+
202
+ // Find all the files including $search in their filename.
203
+ foreach ( $dirlist as $filename => $filedata ) {
204
+ if ( false !== strpos( $filename, $search ) ) {
205
+ $matches[ $filename ] = $filedata;
206
+ }
207
+ }
208
+
209
+ return $matches;
210
+ }
211
+
212
  /**
213
  * Get and return the backup directory path.
214
  *
225
 
226
  // If we have it in the settings, then use it.
227
  $settings = $this->core->settings->get_settings();
228
+ if ( ! empty( $settings['backup_directory'] ) &&
229
+ $this->core->wp_filesystem->is_writable( $settings['backup_directory'] ) ) {
230
+ $this->set( $settings['backup_directory'] );
231
+
232
  return $this->backup_directory;
233
  }
234
 
336
 
337
  $this->set( $backup_directory );
338
 
339
+ $settings = $this->core->settings->get_settings();
340
+
341
  $settings['backup_directory'] = $backup_directory;
342
+
343
  $this->core->settings->save( $settings );
344
 
345
  return $this->backup_directory;
admin/class-boldgrid-backup-admin-config.php CHANGED
@@ -274,10 +274,15 @@ class Boldgrid_Backup_Admin_Config {
274
  */
275
  public function set_lang() {
276
  $this->lang = array(
277
- 'website_size' => esc_html__( 'Website Size:', 'boldgrid-backup' ),
278
- 'database_size' => esc_html__( 'Database Size:', 'boldgrid-backup' ),
279
- 'of' => esc_html__( 'of', 'boldgrid-backup' ),
280
- 'xmark' => '&#10007;',
 
 
 
 
 
281
  );
282
  }
283
 
274
  */
275
  public function set_lang() {
276
  $this->lang = array(
277
+ 'website_size' => esc_html__( 'Website Size:', 'boldgrid-backup' ),
278
+ 'database_size' => esc_html__( 'Database Size:', 'boldgrid-backup' ),
279
+ 'of' => esc_html__( 'of', 'boldgrid-backup' ),
280
+ 'xmark' => '&#10007;',
281
+ 'update' => esc_html__( 'Update', 'boldgrid-backup' ),
282
+ 'updating' => esc_html__( 'Updating...', 'boldgrid-backup' ),
283
+ 'updated' => esc_html__( 'Updated!', 'boldgrid-backup' ),
284
+ 'failed_to_update' => esc_html__( 'Failed to update: ', 'boldgrid-backup' ),
285
+ 'unknown_error' => esc_html__( 'Unknown error.', 'boldgrid-backup' ),
286
  );
287
  }
288
 
admin/class-boldgrid-backup-admin-core.php CHANGED
@@ -499,17 +499,25 @@ class Boldgrid_Backup_Admin_Core {
499
  */
500
  public $scheduler;
501
 
 
 
 
 
 
 
 
 
 
502
  /**
503
  * Constructor.
504
  *
505
  * @since 1.0
506
  *
507
- * @global $wp_filesystem.
508
  */
509
  public function __construct() {
510
  WP_Filesystem();
511
  global $wp_filesystem;
512
-
513
  global $pagenow;
514
 
515
  $this->doing_cron = ( defined( 'DOING_CRON' ) && DOING_CRON ) || isset( $_GET['doing_wp_cron'] ); // phpcs:ignore WordPress.CSRF.NonceVerification.NoNonceVerification
@@ -611,6 +619,8 @@ class Boldgrid_Backup_Admin_Core {
611
 
612
  $this->cron_log = new Boldgrid_Backup_Admin_Cron_Log( $this );
613
 
 
 
614
  // Ensure there is a backup identifier.
615
  $this->get_backup_identifier();
616
 
@@ -742,13 +752,14 @@ class Boldgrid_Backup_Admin_Core {
742
  *
743
  * @since 1.0
744
  *
745
- * @param string $command A command string to be executed.
746
- * @param array $available_exec_functions An array of available execution functions.
747
- * @param bool $success or failure of the operation, passed back to the caller.
748
- * @param int $return_var If present, the return_var, passed back to the caller.
 
749
  * @return string|bool Returns the command output or FALSE on error.
750
  */
751
- public function execute_command( $command, $available_exec_functions = array(), &$success = false, &$return_var = 0 ) {
752
  // If no command was passed, then fail.
753
  if ( empty( $command ) ) {
754
  return false;
@@ -759,6 +770,11 @@ class Boldgrid_Backup_Admin_Core {
759
  $available_exec_functions = $this->get_execution_functions();
760
  }
761
 
 
 
 
 
 
762
  // Disable stderr.
763
  if ( ! $this->test->is_windows() && false === strpos( $command, '2>/dev/null' ) ) {
764
  $command .= ' 2>/dev/null';
@@ -949,7 +965,7 @@ class Boldgrid_Backup_Admin_Core {
949
  global $submenu;
950
 
951
  $lang = array(
952
- 'backup_archive' => __( 'Backup Archive', 'boldgrid-backup' ),
953
  'boldgrid_backup' => __( 'BoldGrid Backup', 'boldgrid-backup' ),
954
  'get_premium' => __( 'Get Premium', 'boldgrid-bacukp' ),
955
  'preflight_check' => __( 'Preflight Check', 'boldgrid-backup' ),
@@ -958,13 +974,7 @@ class Boldgrid_Backup_Admin_Core {
958
  );
959
 
960
  // The main slug all sub menu items are children of.
961
- $main_slug = 'boldgrid-backup-settings';
962
-
963
- // The callable function for the settings page.
964
- $settings_page = array(
965
- $this->settings,
966
- 'page_backup_settings',
967
- );
968
 
969
  // The capability required for these menu items to be displayed to the user.
970
  $capability = 'administrator';
@@ -974,10 +984,26 @@ class Boldgrid_Backup_Admin_Core {
974
  $lang['boldgrid_backup'],
975
  $capability,
976
  $main_slug,
977
- $settings_page,
 
 
 
978
  'none'
979
  );
980
 
 
 
 
 
 
 
 
 
 
 
 
 
 
981
  /*
982
  * Add "Settings", formally known as "Backup Settings".
983
  *
@@ -988,20 +1014,10 @@ class Boldgrid_Backup_Admin_Core {
988
  $lang['boldgrid_backup'] . ' ' . $lang['settings'],
989
  $lang['settings'],
990
  $capability,
991
- $main_slug,
992
- $settings_page
993
- );
994
-
995
- // Add "Backup Archive", formally known as "BoldGrid Backup".
996
- add_submenu_page(
997
- $main_slug,
998
- 'BoldGrid ' . $lang['backup_archive'],
999
- $lang['backup_archive'],
1000
- $capability,
1001
- 'boldgrid-backup',
1002
  array(
1003
- $this,
1004
- 'page_archives',
1005
  )
1006
  );
1007
 
@@ -1271,10 +1287,11 @@ class Boldgrid_Backup_Admin_Core {
1271
 
1272
  // If changed, then restore the WP Option for "home".
1273
  if ( $restored_wp_home !== $wp_home ) {
1274
- // Ensure there are no trailing slashes in siteurl.
1275
- $wp_home = untrailingslashit( $wp_home );
1276
 
1277
- update_option( 'home', $wp_home );
 
 
 
1278
  }
1279
 
1280
  // Return success.
@@ -1504,6 +1521,12 @@ class Boldgrid_Backup_Admin_Core {
1504
  public function archive_files( $save = false, $dryrun = false ) {
1505
  $this->pre_auto_update = 'pre_auto_update' === current_filter();
1506
 
 
 
 
 
 
 
1507
  /**
1508
  * Actions to take before any archiving begins.
1509
  *
@@ -1566,6 +1589,8 @@ class Boldgrid_Backup_Admin_Core {
1566
  'folder_include' => $this->folder_exclusion->from_settings( 'include' ),
1567
  'folder_exclude' => $this->folder_exclusion->from_settings( 'exclude' ),
1568
  'table_exclude' => $this->db_omit->get_excluded_tables(),
 
 
1569
  );
1570
 
1571
  // Determine how this backup was triggered.
@@ -1660,6 +1685,12 @@ class Boldgrid_Backup_Admin_Core {
1660
  */
1661
  $info = apply_filters( 'boldgrid_backup_pre_archive_info', $info );
1662
 
 
 
 
 
 
 
1663
  /*
1664
  * Use the chosen compressor to build an archive.
1665
  * If the is no available compressor, then return an error.
@@ -1700,6 +1731,9 @@ class Boldgrid_Backup_Admin_Core {
1700
  break;
1701
  }
1702
 
 
 
 
1703
  $info['total_size'] += $this->filelist->get_total_size( $filelist );
1704
 
1705
  if ( true === $status && ! $this->wp_filesystem->exists( $info['filepath'] ) ) {
@@ -1761,8 +1795,16 @@ class Boldgrid_Backup_Admin_Core {
1761
  */
1762
  do_action( 'boldgrid_backup_post_archive_files', $info );
1763
 
1764
- // Send an email.
1765
- if ( $this->email->user_wants_notification( 'backup' ) && $this->doing_ajax ) {
 
 
 
 
 
 
 
 
1766
  $email_parts = $this->email->post_archive_parts( $info );
1767
  $email_body = $email_parts['body']['main'] . $email_parts['body']['signature'];
1768
  $info['mail_success'] = $this->email->send( $email_parts['subject'], $email_body );
@@ -1781,6 +1823,12 @@ class Boldgrid_Backup_Admin_Core {
1781
  update_option( 'boldgrid_backup_latest_backup', $info );
1782
  }
1783
 
 
 
 
 
 
 
1784
  // Return the array of archive information.
1785
  return $info;
1786
  }
@@ -2414,6 +2462,8 @@ class Boldgrid_Backup_Admin_Core {
2414
  * a message should be displayed with the path to download using an alternate method.
2415
  *
2416
  * @since 1.0
 
 
2417
  */
2418
  public function download_archive_file_callback() {
2419
  // Verify nonce, or die.
@@ -2475,27 +2525,8 @@ class Boldgrid_Backup_Admin_Core {
2475
 
2476
  $filesize = $archives[ $download_key ]['filesize'];
2477
 
2478
- // Send header.
2479
- header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
2480
- header( 'Content-Transfer-Encoding: binary' );
2481
- header( 'Content-Type: binary/octet-stream' );
2482
- header( 'Content-Length: ' . $filesize );
2483
-
2484
- // Check and flush output buffer if needed.
2485
- if ( 0 !== ob_get_level() ) {
2486
- ob_end_flush();
2487
- }
2488
-
2489
- // Close any PHP session, so another session can open during the download.
2490
- session_write_close();
2491
-
2492
- // Send the file. Not finding a replacement in $wp_filesystem.
2493
- // phpcs:disable
2494
- readfile( $filepath );
2495
- // phpcs:enable
2496
-
2497
- // Exit.
2498
- wp_die();
2499
  }
2500
 
2501
  /**
@@ -2734,9 +2765,17 @@ class Boldgrid_Backup_Admin_Core {
2734
  // Get backup settings.
2735
  $settings = $this->settings->get_settings();
2736
 
2737
- // Get archive list.
2738
  $archives = $this->get_archive_list();
2739
 
 
 
 
 
 
 
 
 
 
2740
  // Get the archives file count.
2741
  $archives_count = count( $archives );
2742
 
499
  */
500
  public $scheduler;
501
 
502
+ /**
503
+ * The public download class object.
504
+ *
505
+ * @since 1.7.0
506
+ * @access public
507
+ * @var Boldgrid_Backup_Download
508
+ */
509
+ public $download;
510
+
511
  /**
512
  * Constructor.
513
  *
514
  * @since 1.0
515
  *
516
+ * @global $wp_filesystem
517
  */
518
  public function __construct() {
519
  WP_Filesystem();
520
  global $wp_filesystem;
 
521
  global $pagenow;
522
 
523
  $this->doing_cron = ( defined( 'DOING_CRON' ) && DOING_CRON ) || isset( $_GET['doing_wp_cron'] ); // phpcs:ignore WordPress.CSRF.NonceVerification.NoNonceVerification
619
 
620
  $this->cron_log = new Boldgrid_Backup_Admin_Cron_Log( $this );
621
 
622
+ $this->download = new Boldgrid_Backup_Download( $this );
623
+
624
  // Ensure there is a backup identifier.
625
  $this->get_backup_identifier();
626
 
752
  *
753
  * @since 1.0
754
  *
755
+ * @param string $command A command string to be executed.
756
+ * @param array $available_exec_functions An array of available execution functions.
757
+ * @param bool $success Success or failure of the operation, passed back.
758
+ * @param int $return_var If present, the return_var, passed back.
759
+ * @param string $filepath An optional file path to write the output.
760
  * @return string|bool Returns the command output or FALSE on error.
761
  */
762
+ public function execute_command( $command, $available_exec_functions = array(), &$success = false, &$return_var = 0, $filepath = null ) {
763
  // If no command was passed, then fail.
764
  if ( empty( $command ) ) {
765
  return false;
770
  $available_exec_functions = $this->get_execution_functions();
771
  }
772
 
773
+ // If an output filepath is supplied, and the directory is writable, then write to file.
774
+ if ( $filepath && $this->wp_filesystem->is_writable( dirname( $filepath ) ) ) {
775
+ $command .= ' > ' . wp_normalize_path( $filepath );
776
+ }
777
+
778
  // Disable stderr.
779
  if ( ! $this->test->is_windows() && false === strpos( $command, '2>/dev/null' ) ) {
780
  $command .= ' 2>/dev/null';
965
  global $submenu;
966
 
967
  $lang = array(
968
+ 'backup_archive' => __( 'Backup Archives', 'boldgrid-backup' ),
969
  'boldgrid_backup' => __( 'BoldGrid Backup', 'boldgrid-backup' ),
970
  'get_premium' => __( 'Get Premium', 'boldgrid-bacukp' ),
971
  'preflight_check' => __( 'Preflight Check', 'boldgrid-backup' ),
974
  );
975
 
976
  // The main slug all sub menu items are children of.
977
+ $main_slug = 'boldgrid-backup';
 
 
 
 
 
 
978
 
979
  // The capability required for these menu items to be displayed to the user.
980
  $capability = 'administrator';
984
  $lang['boldgrid_backup'],
985
  $capability,
986
  $main_slug,
987
+ array(
988
+ $this,
989
+ 'page_archives',
990
+ ),
991
  'none'
992
  );
993
 
994
+ // Add "Backup Archive", formally known as "BoldGrid Backup".
995
+ add_submenu_page(
996
+ $main_slug,
997
+ 'BoldGrid ' . $lang['backup_archive'],
998
+ $lang['backup_archive'],
999
+ $capability,
1000
+ 'boldgrid-backup',
1001
+ array(
1002
+ $this,
1003
+ 'page_archives',
1004
+ )
1005
+ );
1006
+
1007
  /*
1008
  * Add "Settings", formally known as "Backup Settings".
1009
  *
1014
  $lang['boldgrid_backup'] . ' ' . $lang['settings'],
1015
  $lang['settings'],
1016
  $capability,
1017
+ 'boldgrid-backup-settings',
 
 
 
 
 
 
 
 
 
 
1018
  array(
1019
+ $this->settings,
1020
+ 'page_backup_settings',
1021
  )
1022
  );
1023
 
1287
 
1288
  // If changed, then restore the WP Option for "home".
1289
  if ( $restored_wp_home !== $wp_home ) {
 
 
1290
 
1291
+ // There may be a filter, so remove it.
1292
+ remove_all_filters( 'pre_update_option_home' );
1293
+
1294
+ update_option( 'home', untrailingslashit( $wp_home ) );
1295
  }
1296
 
1297
  // Return success.
1521
  public function archive_files( $save = false, $dryrun = false ) {
1522
  $this->pre_auto_update = 'pre_auto_update' === current_filter();
1523
 
1524
+ Boldgrid_Backup_Admin_In_Progress_Data::set_args(
1525
+ array(
1526
+ 'status' => __( 'Initializing backup', 'boldgrid-backup' ),
1527
+ )
1528
+ );
1529
+
1530
  /**
1531
  * Actions to take before any archiving begins.
1532
  *
1589
  'folder_include' => $this->folder_exclusion->from_settings( 'include' ),
1590
  'folder_exclude' => $this->folder_exclusion->from_settings( 'exclude' ),
1591
  'table_exclude' => $this->db_omit->get_excluded_tables(),
1592
+ 'title' => ! empty( $_POST['backup_title'] ) ? stripslashes( $_POST['backup_title'] ) : null, // phpcs:ignore WordPress.CSRF.NonceVerification,WordPress.Arrays.ArrayDeclarationSpacing.ArrayItemNoNewLine
1593
+ 'description' => ! empty( $_POST['backup_description'] ) ? stripslashes( $_POST['backup_description'] ) : null, // phpcs:ignore WordPress.CSRF.NonceVerification,WordPress.Arrays.ArrayDeclarationSpacing.ArrayItemNoNewLine
1594
  );
1595
 
1596
  // Determine how this backup was triggered.
1685
  */
1686
  $info = apply_filters( 'boldgrid_backup_pre_archive_info', $info );
1687
 
1688
+ Boldgrid_Backup_Admin_In_Progress_Data::set_args(
1689
+ array(
1690
+ 'total_files_todo' => count( $filelist ),
1691
+ )
1692
+ );
1693
+
1694
  /*
1695
  * Use the chosen compressor to build an archive.
1696
  * If the is no available compressor, then return an error.
1731
  break;
1732
  }
1733
 
1734
+ Boldgrid_Backup_Admin_In_Progress_Data::set_arg( 'status', __( 'Wrapping things up...', 'boldgrid-backup' ) );
1735
+ Boldgrid_Backup_Admin_In_Progress_Data::set_arg( 'percentage', 100 );
1736
+
1737
  $info['total_size'] += $this->filelist->get_total_size( $filelist );
1738
 
1739
  if ( true === $status && ! $this->wp_filesystem->exists( $info['filepath'] ) ) {
1795
  */
1796
  do_action( 'boldgrid_backup_post_archive_files', $info );
1797
 
1798
+ /*
1799
+ * Send an email to the user, RIGHT NOW.
1800
+ *
1801
+ * Only send an email to the user now IF they are manually creating a backup. If this backup
1802
+ * was created during a scheduled backup, the user will get an email from the jobs queue.
1803
+ * Scheduled backups receive email notifications from the jobs queue because that email will
1804
+ * not only include the standard info about the backup (which we're sending now), it will
1805
+ * also include info about other jobs that were ran (such as uploading the backup remotely).
1806
+ */
1807
+ if ( $this->email->user_wants_notification( 'backup' ) && ! $is_scheduled_backup ) {
1808
  $email_parts = $this->email->post_archive_parts( $info );
1809
  $email_body = $email_parts['body']['main'] . $email_parts['body']['signature'];
1810
  $info['mail_success'] = $this->email->send( $email_parts['subject'], $email_body );
1823
  update_option( 'boldgrid_backup_latest_backup', $info );
1824
  }
1825
 
1826
+ Boldgrid_Backup_Admin_In_Progress_Data::set_args(
1827
+ array(
1828
+ 'status' => __( 'Backup complete!', 'boldgrid-backup' ),
1829
+ )
1830
+ );
1831
+
1832
  // Return the array of archive information.
1833
  return $info;
1834
  }
2462
  * a message should be displayed with the path to download using an alternate method.
2463
  *
2464
  * @since 1.0
2465
+ *
2466
+ * @see Boldgrid_Backup_File::send_file()
2467
  */
2468
  public function download_archive_file_callback() {
2469
  // Verify nonce, or die.
2525
 
2526
  $filesize = $archives[ $download_key ]['filesize'];
2527
 
2528
+ // Send the file and die nicely.
2529
+ Boldgrid_Backup_File::send_file( $filepath, $filesize );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2530
  }
2531
 
2532
  /**
2765
  // Get backup settings.
2766
  $settings = $this->settings->get_settings();
2767
 
 
2768
  $archives = $this->get_archive_list();
2769
 
2770
+ // Remove from the list of archives any that have been flagged as being protected.
2771
+ foreach ( $archives as $key => $archive ) {
2772
+ $this->archive->init( $archive['filepath'] );
2773
+ if ( '1' === $this->archive->get_attribute( 'protect' ) ) {
2774
+ unset( $archives[ $key ] );
2775
+ }
2776
+ }
2777
+ $archives = array_values( $archives );
2778
+
2779
  // Get the archives file count.
2780
  $archives_count = count( $archives );
2781
 
admin/class-boldgrid-backup-admin-db-dump.php CHANGED
@@ -54,6 +54,14 @@ class Boldgrid_Backup_Admin_Db_Dump {
54
  return array( 'error' => esc_html__( 'No tables selected to backup.', 'boldgrid-backup' ) );
55
  }
56
 
 
 
 
 
 
 
 
 
57
  /**
58
  * Take action before a database is dumped.
59
  *
54
  return array( 'error' => esc_html__( 'No tables selected to backup.', 'boldgrid-backup' ) );
55
  }
56
 
57
+ Boldgrid_Backup_Admin_In_Progress_Data::set_args(
58
+ array(
59
+ 'status' => __( 'Backing up database...', 'boldgrid-backup' ),
60
+ 'tables' => $include_tables,
61
+ 'step' => 1,
62
+ )
63
+ );
64
+
65
  /**
66
  * Take action before a database is dumped.
67
  *
admin/class-boldgrid-backup-admin-email.php CHANGED
@@ -87,7 +87,7 @@ class Boldgrid_Backup_Admin_Email {
87
  'generic' => $this->core->config->get_is_premium() ? '' : sprintf(
88
  // translators: 1: URL address.
89
  __( 'Want to store your backups on Amazon S3, restore individual files with just a click, and have access to more tools? Get BoldGrid Backup Premium! - %1$s', 'boldgrid-backup' ),
90
- Boldgrid_Backup_Admin_Go_Pro::$url
91
  ) . "\n\n",
92
  );
93
  }
87
  'generic' => $this->core->config->get_is_premium() ? '' : sprintf(
88
  // translators: 1: URL address.
89
  __( 'Want to store your backups on Amazon S3, restore individual files with just a click, and have access to more tools? Get BoldGrid Backup Premium! - %1$s', 'boldgrid-backup' ),
90
+ $this->core->go_pro->get_premium_url( 'bgbkup-email' )
91
  ) . "\n\n",
92
  );
93
  }
admin/class-boldgrid-backup-admin-go-pro.php CHANGED
@@ -91,7 +91,7 @@ class Boldgrid_Backup_Admin_Go_Pro {
91
  'message' => '<p>' . sprintf(
92
  // translators: 1: URL address for the upgrade page.
93
  __( 'Thank you for activating the <strong>BoldGrid Backup Premium Extension</strong>! Before you can begin using all of the premium features, you must <a href="%2$s">add your premium key</a>. If you are using an Official BoldGrid Host, contact them or login to their management system to retrieve your Premium key. Otherwise, please visit <a href="%1$s" target="_blank">BoldGrid Central</a> to upgrade.', 'boldgrid-backup' ),
94
- self::$url,
95
  admin_url( 'admin.php?page=boldgrid-backup-settings&section=connect_key' )
96
  ) . '</p>',
97
  ),
@@ -126,7 +126,9 @@ class Boldgrid_Backup_Admin_Go_Pro {
126
  * @param string $text Button text.
127
  * @return string
128
  */
129
- public function get_premium_button( $url = 'https://www.boldgrid.com/update-backup', $text = 'Get Premium' ) {
 
 
130
  return sprintf(
131
  '
132
  <a href="%1$s" class="button button-success" target="_blank">%2$s</a>',
@@ -134,4 +136,19 @@ class Boldgrid_Backup_Admin_Go_Pro {
134
  $text
135
  );
136
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  }
91
  'message' => '<p>' . sprintf(
92
  // translators: 1: URL address for the upgrade page.
93
  __( 'Thank you for activating the <strong>BoldGrid Backup Premium Extension</strong>! Before you can begin using all of the premium features, you must <a href="%2$s">add your premium key</a>. If you are using an Official BoldGrid Host, contact them or login to their management system to retrieve your Premium key. Otherwise, please visit <a href="%1$s" target="_blank">BoldGrid Central</a> to upgrade.', 'boldgrid-backup' ),
94
+ $this->get_premium_url( 'bgbkup-premium-activate' ),
95
  admin_url( 'admin.php?page=boldgrid-backup-settings&section=connect_key' )
96
  ) . '</p>',
97
  ),
126
  * @param string $text Button text.
127
  * @return string
128
  */
129
+ public function get_premium_button( $url = null, $text = 'Get Premium' ) {
130
+ $url = ! empty( $url ) ? $url : $this->get_premium_url();
131
+
132
  return sprintf(
133
  '
134
  <a href="%1$s" class="button button-success" target="_blank">%2$s</a>',
136
  $text
137
  );
138
  }
139
+
140
+ /**
141
+ * Get a "Get Premium" url.
142
+ *
143
+ * @since 1.7.0
144
+ *
145
+ * @param string $source Source to append to url.
146
+ * @param string $url URL address for the upgrade page.
147
+ * @return string
148
+ */
149
+ public function get_premium_url( $source = 'bgbkup', $url = 'https://www.boldgrid.com/update-backup' ) {
150
+ $url = add_query_arg( 'source', $source, $url );
151
+
152
+ return $url;
153
+ }
154
  }
admin/class-boldgrid-backup-admin-in-progress-data.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class: Boldgrid_Backup_Admin_In_Progress_Data
4
+ *
5
+ * This class used for managing the data used by the Boldgrid_Backup_Admin_In_Progress class.
6
+ *
7
+ * @link https://www.boldgrid.com
8
+ * @since 1.7.0
9
+ *
10
+ * @package Boldgrid_Backup
11
+ * @subpackage Boldgrid_Backup/admin
12
+ * @copyright BoldGrid
13
+ * @version $Id$
14
+ * @author BoldGrid <support@boldgrid.com>
15
+ */
16
+
17
+ /**
18
+ * Class: Boldgrid_Backup_Admin_In_Progress_Data
19
+ *
20
+ * @since 1.7.0
21
+ */
22
+ class Boldgrid_Backup_Admin_In_Progress_Data {
23
+
24
+ /**
25
+ * Option name in which data is stored.
26
+ *
27
+ * @since 1.7.0
28
+ * @var string
29
+ */
30
+ public static $option_name = 'boldgrid_backup_in_progress_data';
31
+
32
+ /**
33
+ * Delete one arguement.
34
+ *
35
+ * @since 1.7.0
36
+ *
37
+ * @param string $arg The key.
38
+ */
39
+ public static function delete_arg( $arg ) {
40
+ $args = self::get_args();
41
+
42
+ if ( isset( $args[ $arg ] ) ) {
43
+ unset( $args[ $arg ] );
44
+ }
45
+
46
+ update_option( self::$option_name, $args );
47
+ }
48
+
49
+ /**
50
+ * Get one argument.
51
+ *
52
+ * @since 1.7.0
53
+ *
54
+ * @return mixed
55
+ */
56
+ public static function get_arg( $key ) {
57
+ $args = get_option( self::$option_name );
58
+
59
+ return isset( $args[ $key ] ) ? $args[ $key ] : false;
60
+ }
61
+
62
+ /**
63
+ * Get all arguments.
64
+ *
65
+ * @since 1.7.0
66
+ *
67
+ * @return array
68
+ */
69
+ public static function get_args() {
70
+ return get_option( self::$option_name );
71
+ }
72
+
73
+ /**
74
+ * Get required markup to show the progress bar.
75
+ *
76
+ * Generally displayed under a "Backup Now" button.
77
+ *
78
+ * @since 1.7.0
79
+ */
80
+ public static function get_markup( $label = null ) {
81
+ $label = ! empty( $label ) ? $label : __( 'Initializing backup...', 'boldgrid-backup' );
82
+
83
+ $steps = '<div id="boldgrid_backup_in_progress_steps">
84
+ <div class="step" data-step="1">' . esc_html__( 'Backing up database...', 'boldgrid-backup' ) . '</div>
85
+ <div class="step" data-step="2">' . esc_html__( 'Adding files to archive...', 'boldgrid-backup' ) . '</div>
86
+ <div class="step" data-step="3">' . esc_html__( 'Saving archive to disk...', 'boldgrid-backup' ) . '</div>
87
+ </div>';
88
+
89
+ $progress_bar = '<div id="boldgrid-backup-in-progress-bar">
90
+ <div class="progress-label">' . esc_html( $label ) . '</div>
91
+ <div id="last_file_archived"></div>
92
+ </div>';
93
+
94
+ return '<div id="boldgrid_backup_in_progress_container" class="hidden">' . $steps . $progress_bar . '</div>';
95
+ }
96
+
97
+ /**
98
+ * Set one arguement, a key / value pair.
99
+ *
100
+ * @since 1.7.0
101
+ *
102
+ * @param string $arg The key.
103
+ * @param string $value The value.
104
+ */
105
+ public static function set_arg( $arg, $value ) {
106
+ $args = self::get_args();
107
+
108
+ $args[ $arg ] = $value;
109
+
110
+ update_option( self::$option_name, $args );
111
+ }
112
+
113
+ /**
114
+ * Set arguments.
115
+ *
116
+ * @since 1.7.0
117
+ *
118
+ * @param array $args Arguments.
119
+ */
120
+ public static function set_args( $args ) {
121
+ update_option( self::$option_name, $args );
122
+ }
123
+ }
admin/class-boldgrid-backup-admin-in-progress.php CHANGED
@@ -72,6 +72,8 @@ class Boldgrid_Backup_Admin_In_Progress {
72
  */
73
  wp_enqueue_script( 'heartbeat' );
74
 
 
 
75
  $elapsed = time() - $in_progress;
76
  $limit = 15 * MINUTE_IN_SECONDS;
77
 
@@ -146,16 +148,18 @@ class Boldgrid_Backup_Admin_In_Progress {
146
  return false;
147
  }
148
 
149
- $notice = array(
 
 
 
 
 
 
 
 
 
150
  'class' => 'notice notice-warning boldgrid-backup-in-progress',
151
- 'message' => sprintf(
152
- // translators: 1: Time difference.
153
- __(
154
- 'BoldGrid Backup began archiving your website %1$s ago.',
155
- 'boldgrid-backup'
156
- ),
157
- human_time_diff( $in_progress, time() )
158
- ),
159
  'heading' => __( 'BoldGrid Backup - Backup in progress', 'boldgrid-backup' ),
160
  );
161
 
@@ -181,6 +185,47 @@ class Boldgrid_Backup_Admin_In_Progress {
181
  return $markup;
182
  }
183
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  /**
185
  * Take action when the heartbeat is received.
186
  *
@@ -206,6 +251,16 @@ class Boldgrid_Backup_Admin_In_Progress {
206
  // Our "backup complete!" admin notice.
207
  $response['boldgrid_backup_complete'] = $this->core->notice->get_backup_complete();
208
 
 
 
 
 
 
 
 
 
 
 
209
  return $response;
210
  }
211
 
72
  */
73
  wp_enqueue_script( 'heartbeat' );
74
 
75
+ wp_enqueue_script( 'jquery-ui-progressbar' );
76
+
77
  $elapsed = time() - $in_progress;
78
  $limit = 15 * MINUTE_IN_SECONDS;
79
 
148
  return false;
149
  }
150
 
151
+ /*
152
+ * Create our notice for atop the page.
153
+ *
154
+ * Initially started out as "backup in progress". Has expanded to include a progress bar.
155
+ */
156
+ $loading = __( 'Loading...', 'bgtfw' );
157
+ // translators: 1: The time since the last backup was initiated.
158
+ $message = '<p>' . sprintf( __( 'BoldGrid Backup began archiving your website %1$s ago.', 'boldgrid-backup' ), human_time_diff( $in_progress, time() ) ) . '</p>';
159
+ $message .= Boldgrid_Backup_Admin_In_Progress_Data::get_markup( $loading );
160
+ $notice = array(
161
  'class' => 'notice notice-warning boldgrid-backup-in-progress',
162
+ 'message' => $message,
 
 
 
 
 
 
 
163
  'heading' => __( 'BoldGrid Backup - Backup in progress', 'boldgrid-backup' ),
164
  );
165
 
185
  return $markup;
186
  }
187
 
188
+ /**
189
+ * Get details on our temporary zip file.
190
+ *
191
+ * For example, if we're in the middle of saving / closing our backup file, there should be a
192
+ * file.zip.temp file in our backup directory. We are getting the details of that file.
193
+ *
194
+ * @since 1.7.0
195
+ *
196
+ * @return array
197
+ */
198
+ public function get_tmp() {
199
+ $data = array();
200
+
201
+ $dirlist = $this->core->backup_dir->dirlist_containing( '.zip.' );
202
+
203
+ /*
204
+ * We should only have one temp zip file. If we have multiple though, something may have
205
+ * gone recently. Sort by timestamp and use the newest file.
206
+ */
207
+ if ( 1 < count( $dirlist ) ) {
208
+ uasort(
209
+ $dirlist, function( $item1, $item2 ) {
210
+ return $item1['lastmodunix'] < $item2['lastmodunix'] ? 1 : -1;
211
+ }
212
+ );
213
+ }
214
+
215
+ if ( 1 <= count( $dirlist ) ) {
216
+ reset( $dirlist );
217
+ $tmp_filename = key( $dirlist );
218
+
219
+ $data = array(
220
+ 'size' => $dirlist[ $tmp_filename ]['size'],
221
+ 'lastmodunix' => $dirlist[ $tmp_filename ]['lastmodunix'],
222
+ 'size_format' => size_format( $dirlist[ $tmp_filename ]['size'] ),
223
+ );
224
+ }
225
+
226
+ return $data;
227
+ }
228
+
229
  /**
230
  * Take action when the heartbeat is received.
231
  *
251
  // Our "backup complete!" admin notice.
252
  $response['boldgrid_backup_complete'] = $this->core->notice->get_backup_complete();
253
 
254
+ $response['in_progress_data'] = Boldgrid_Backup_Admin_In_Progress_Data::get_args();
255
+
256
+ // Steps to take if we're on the last step, step 3, closing the archive.
257
+ if ( 3 === Boldgrid_Backup_Admin_In_Progress_Data::get_arg( 'step' ) ) {
258
+ $tmp = $this->get_tmp();
259
+ if ( ! empty( $tmp ) ) {
260
+ $response['in_progress_data']['tmp'] = $tmp;
261
+ }
262
+ }
263
+
264
  return $response;
265
  }
266
 
admin/class-boldgrid-backup-admin-notice.php CHANGED
@@ -227,4 +227,23 @@ class Boldgrid_Backup_Admin_Notice {
227
 
228
  return $message;
229
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  }
227
 
228
  return $message;
229
  }
230
+
231
+ /**
232
+ * Display a notice for auto-update settings.
233
+ *
234
+ * @since 1.7.0
235
+ */
236
+ public function display_autoupdate_notice() {
237
+ $message = sprintf(
238
+ // translators: 1: HTML anchor opening tag, 2: HTML anchor closing tag.
239
+ esc_html__(
240
+ 'Auto-Updates can be configured in the %1$sBoldGrid Backup Settings%2$s.',
241
+ 'boldgrid-backup'
242
+ ),
243
+ '<a href="' . admin_url( 'admin.php?page=boldgrid-backup-settings&section=section_auto_updates' ) . '">',
244
+ '</a>'
245
+ );
246
+
247
+ do_action( 'boldgrid_backup_notice', $message, 'notice notice-info is-dismissible' );
248
+ }
249
  }
admin/class-boldgrid-backup-admin-remote.php CHANGED
@@ -80,19 +80,13 @@ class Boldgrid_Backup_Admin_Remote {
80
  *
81
  * @since 1.6.0
82
  *
 
 
 
83
  * @param string $filepath A file path.
84
  */
85
  public function post_download( $filepath ) {
86
- /*
87
- * Restore the log file from the archive so we can get all the juicy
88
- * meta data about the archive.
89
- */
90
- $this->core->archive_log->restore_by_zip( $filepath );
91
-
92
- /*
93
- * Now that we have the log, update the archive's timestamp based upon
94
- * time last modified time in the log.
95
- */
96
  $this->core->archive->reset();
97
  $this->core->archive->init( $filepath );
98
  $this->core->archive->update_timestamp();
80
  *
81
  * @since 1.6.0
82
  *
83
+ * @see Boldgrid_Backup_Admin_Archive::init()
84
+ * @see Boldgrid_Backup_Admin_Archive::update_timestamp()
85
+ *
86
  * @param string $filepath A file path.
87
  */
88
  public function post_download( $filepath ) {
89
+ // Update the archive's timestamp based upon time last modified time in the log.
 
 
 
 
 
 
 
 
 
90
  $this->core->archive->reset();
91
  $this->core->archive->init( $filepath );
92
  $this->core->archive->update_timestamp();
admin/class-boldgrid-backup-admin-settings.php CHANGED
@@ -157,13 +157,23 @@ class Boldgrid_Backup_Admin_Settings {
157
  }
158
 
159
  // Other settings.
160
- $settings['auto_backup'] = (
161
  ! isset( $settings['auto_backup'] ) || ! empty( $settings['auto_backup'] ) ? 1 : 0
162
  );
 
163
  $settings['auto_rollback'] = (
164
  ! isset( $settings['auto_rollback'] ) || ! empty( $settings['auto_rollback'] ) ?
165
  1 : 0
166
  );
 
 
 
 
 
 
 
 
 
167
  } else {
168
  // Define defaults.
169
  // Days of the week.
@@ -181,7 +191,7 @@ class Boldgrid_Backup_Admin_Settings {
181
  $settings['schedule']['tod_a'] = 'AM';
182
 
183
  // Other settings.
184
- $settings['retention_count'] = 5;
185
  $settings['notification_email'] = $this->core->config->get_admin_email();
186
  $settings['notifications']['backup'] = 1;
187
  $settings['notifications']['restore'] = 1;
@@ -189,16 +199,6 @@ class Boldgrid_Backup_Admin_Settings {
189
  $settings['auto_rollback'] = 1;
190
  }
191
 
192
- $boldgrid_settings = get_site_option( 'boldgrid_settings' );
193
-
194
- $settings['plugin_autoupdate'] = (
195
- ! empty( $boldgrid_settings['plugin_autoupdate'] ) ? 1 : 0
196
- );
197
-
198
- $settings['theme_autoupdate'] = (
199
- ! empty( $boldgrid_settings['theme_autoupdate'] ) ? 1 : 0
200
- );
201
-
202
  if ( empty( $settings['remote'] ) ) {
203
  $settings['remote'] = array();
204
  }
@@ -268,14 +268,13 @@ class Boldgrid_Backup_Admin_Settings {
268
  private function update_settings() {
269
  $update_errors = array();
270
 
271
- // Verify nonce.
272
- check_admin_referer( 'boldgrid-backup-settings', 'settings_auth' );
273
-
274
- // Get the retention count.
275
- if ( isset( $_POST['retention_count'] ) ) {
276
- $retention_count = intval( $_POST['retention_count'] );
277
- } else {
278
- $retention_count = $this->core->config->get_default_retention();
279
  }
280
 
281
  // Check for settings update.
@@ -384,10 +383,6 @@ class Boldgrid_Backup_Admin_Settings {
384
  }
385
 
386
  // Validate input for other settings.
387
- $settings['retention_count'] = (
388
- isset( $_POST['retention_count'] ) ? (int) $_POST['retention_count'] : 5
389
- );
390
-
391
  $settings['notifications']['backup'] = (
392
  ( isset( $_POST['notify_backup'] ) && '1' === $_POST['notify_backup'] ) ? 1 : 0
393
  );
@@ -410,88 +405,6 @@ class Boldgrid_Backup_Admin_Settings {
410
  $settings['notification_email'] = sanitize_email( $_POST['notification_email'] );
411
  }
412
 
413
- $boldgrid_settings['plugin_autoupdate'] = (
414
- ( isset( $_POST['plugin_autoupdate'] ) && '1' === $_POST['plugin_autoupdate'] ) ?
415
- 1 : 0
416
- );
417
-
418
- $boldgrid_settings['theme_autoupdate'] = (
419
- ( isset( $_POST['theme_autoupdate'] ) && '1' === $_POST['theme_autoupdate'] ) ?
420
- 1 : 0
421
- );
422
-
423
- unset( $settings['plugin_autoupdate'], $settings['theme_autoupdate'] );
424
-
425
- // Get the current backup directory path.
426
- $backup_dir_changed = false;
427
- $original_backup_directory = ! empty( $settings['backup_directory'] ) ? $settings['backup_directory'] : false;
428
-
429
- if ( ! empty( $_POST['backup_directory'] ) ) {
430
- $post_backup_directory = trim( $_POST['backup_directory'] );
431
- $post_backup_directory = untrailingslashit( $post_backup_directory );
432
- $post_backup_directory = str_replace( '\\\\', '\\', $post_backup_directory );
433
- }
434
-
435