BackUpWordPress - Version 3.6.2

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

Code changes from version 3.6.1 to 3.6.2

Files changed (86) hide show
  1. admin/actions.php +2 -0
  2. admin/schedule-form-excludes.php +130 -60
  3. assets/hmbkp.min.js +23 -1
  4. backupwordpress.php +1 -1
  5. classes/backup/class-backup-engine-database-mysqldump.php +1 -37
  6. classes/class-plugin.php +3 -2
  7. classes/class-scheduled-backup.php +6 -0
  8. classes/class-schedules.php +10 -3
  9. classes/class-site-size.php +34 -7
  10. composer.lock +10 -10
  11. languages/backupwordpress.pot +42 -41
  12. readme.txt +13 -3
  13. vendor/composer/autoload_classmap.php +0 -65
  14. vendor/composer/installed.json +12 -12
  15. vendor/symfony/finder/Adapter/AbstractAdapter.php +0 -0
  16. vendor/symfony/finder/Adapter/AbstractFindAdapter.php +0 -0
  17. vendor/symfony/finder/Adapter/AdapterInterface.php +0 -0
  18. vendor/symfony/finder/Adapter/BsdFindAdapter.php +0 -0
  19. vendor/symfony/finder/Adapter/GnuFindAdapter.php +0 -0
  20. vendor/symfony/finder/Adapter/PhpAdapter.php +0 -0
  21. vendor/symfony/finder/CHANGELOG.md +0 -0
  22. vendor/symfony/finder/Comparator/Comparator.php +0 -0
  23. vendor/symfony/finder/Comparator/DateComparator.php +0 -0
  24. vendor/symfony/finder/Comparator/NumberComparator.php +0 -0
  25. vendor/symfony/finder/Exception/AccessDeniedException.php +0 -0
  26. vendor/symfony/finder/Exception/AdapterFailureException.php +0 -0
  27. vendor/symfony/finder/Exception/ExceptionInterface.php +0 -0
  28. vendor/symfony/finder/Exception/OperationNotPermitedException.php +0 -0
  29. vendor/symfony/finder/Exception/ShellCommandFailureException.php +0 -0
  30. vendor/symfony/finder/Expression/Expression.php +2 -2
  31. vendor/symfony/finder/Expression/Glob.php +0 -0
  32. vendor/symfony/finder/Expression/Regex.php +0 -0
  33. vendor/symfony/finder/Expression/ValueInterface.php +0 -0
  34. vendor/symfony/finder/Finder.php +28 -28
  35. vendor/symfony/finder/Glob.php +0 -0
  36. vendor/symfony/finder/Iterator/CustomFilterIterator.php +0 -0
  37. vendor/symfony/finder/Iterator/DateRangeFilterIterator.php +0 -0
  38. vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php +0 -0
  39. vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php +0 -0
  40. vendor/symfony/finder/Iterator/FilePathsIterator.php +0 -0
  41. vendor/symfony/finder/Iterator/FileTypeFilterIterator.php +0 -0
  42. vendor/symfony/finder/Iterator/FilecontentFilterIterator.php +0 -0
  43. vendor/symfony/finder/Iterator/FilenameFilterIterator.php +0 -0
  44. vendor/symfony/finder/Iterator/FilterIterator.php +0 -0
  45. vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php +0 -0
  46. vendor/symfony/finder/Iterator/PathFilterIterator.php +1 -1
  47. vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php +0 -0
  48. vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php +0 -0
  49. vendor/symfony/finder/Iterator/SortableIterator.php +0 -0
  50. vendor/symfony/finder/LICENSE +0 -0
  51. vendor/symfony/finder/Shell/Command.php +0 -0
  52. vendor/symfony/finder/Shell/Shell.php +0 -0
  53. vendor/symfony/finder/SplFileInfo.php +0 -0
  54. vendor/symfony/finder/composer.json +0 -0
  55. vendor/symfony/finder/phpunit.xml.dist +0 -0
  56. vendor/symfony/process/CHANGELOG.md +0 -0
  57. vendor/symfony/process/Exception/ExceptionInterface.php +0 -0
  58. vendor/symfony/process/Exception/InvalidArgumentException.php +0 -0
  59. vendor/symfony/process/Exception/LogicException.php +0 -0
  60. vendor/symfony/process/Exception/ProcessFailedException.php +0 -0
  61. vendor/symfony/process/Exception/ProcessTimedOutException.php +0 -0
  62. vendor/symfony/process/Exception/RuntimeException.php +0 -0
  63. vendor/symfony/process/ExecutableFinder.php +0 -0
  64. vendor/symfony/process/LICENSE +0 -0
  65. vendor/symfony/process/PhpExecutableFinder.php +0 -0
  66. vendor/symfony/process/PhpProcess.php +0 -0
  67. vendor/symfony/process/Pipes/AbstractPipes.php +6 -8
  68. vendor/symfony/process/Pipes/PipesInterface.php +3 -3
  69. vendor/symfony/process/Pipes/UnixPipes.php +0 -0
  70. vendor/symfony/process/Pipes/WindowsPipes.php +26 -6
  71. vendor/symfony/process/Process.php +13 -13
  72. vendor/symfony/process/ProcessBuilder.php +1 -1
  73. vendor/symfony/process/ProcessUtils.php +4 -1
  74. vendor/symfony/process/Tests/ExecutableFinderTest.php +0 -0
  75. vendor/symfony/process/Tests/NonStopableProcess.php +0 -0
  76. vendor/symfony/process/Tests/PhpExecutableFinderTest.php +0 -0
  77. vendor/symfony/process/Tests/PhpProcessTest.php +0 -0
  78. vendor/symfony/process/Tests/PipeStdinInStdoutStdErrStreamSelect.php +0 -0
  79. vendor/symfony/process/Tests/ProcessBuilderTest.php +0 -0
  80. vendor/symfony/process/Tests/ProcessFailedExceptionTest.php +0 -0
  81. vendor/symfony/process/Tests/ProcessTest.php +27 -22
  82. vendor/symfony/process/Tests/ProcessUtilsTest.php +0 -0
  83. vendor/symfony/process/Tests/SignalListener.php +0 -0
  84. vendor/symfony/process/composer.json +0 -0
  85. vendor/symfony/process/phpunit.xml.dist +0 -0
  86. whitelist-html/whitelist-html.php +102 -0
admin/actions.php CHANGED
@@ -411,6 +411,7 @@ function add_exclude_rule() {
411
  $schedule->set_excludes( $exclude_rule, true );
412
 
413
  $schedule->save();
 
414
 
415
  wp_safe_redirect( wp_get_referer(), '303' );
416
 
@@ -441,6 +442,7 @@ function remove_exclude_rule() {
441
  $schedule->set_excludes( array_diff( $excludes->get_user_excludes(), (array) $exclude_rule_to_remove ) );
442
 
443
  $schedule->save();
 
444
 
445
  wp_safe_redirect( wp_get_referer(), '303' );
446
 
411
  $schedule->set_excludes( $exclude_rule, true );
412
 
413
  $schedule->save();
414
+ delete_transient( 'hmbkp_root_size' );
415
 
416
  wp_safe_redirect( wp_get_referer(), '303' );
417
 
442
  $schedule->set_excludes( array_diff( $excludes->get_user_excludes(), (array) $exclude_rule_to_remove ) );
443
 
444
  $schedule->save();
445
+ delete_transient( 'hmbkp_root_size' );
446
 
447
  wp_safe_redirect( wp_get_referer(), '303' );
448
 
admin/schedule-form-excludes.php CHANGED
@@ -2,16 +2,18 @@
2
 
3
  namespace HM\BackUpWordPress;
4
 
5
- $excludes = $schedule->get_excludes();
6
  $user_excludes = $excludes->get_user_excludes(); ?>
7
 
8
  <div class="hmbkp-exclude-settings">
9
 
10
  <h3>
11
- <?php _e( 'Currently Excluded', 'backupwordpress' ); ?>
12
  </h3>
13
 
14
- <p><?php _e( 'We automatically detect and ignore common <abbr title="Version Control Systems">VCS</abbr> folders and other backup plugin folders.', 'backupwordpress' ); ?></p>
 
 
15
 
16
  <table class="widefat">
17
 
@@ -45,20 +47,25 @@ $user_excludes = $excludes->get_user_excludes(); ?>
45
 
46
  <td>
47
 
48
- <?php if ( ( in_array( $exclude, $excludes->get_default_excludes() ) ) || ( Path::get_path() === trailingslashit( Path::get_root() ) . untrailingslashit( $exclude ) ) ) : ?>
 
 
 
49
 
50
- <?php _e( 'Default rule', 'backupwordpress' ); ?>
51
 
52
  <?php elseif ( defined( 'HMBKP_EXCLUDE' ) && false !== strpos( HMBKP_EXCLUDE, $exclude ) ) : ?>
53
 
54
- <?php _e( 'Defined in wp-config.php', 'backupwordpress' ); ?>
55
 
56
  <?php else : ?>
57
 
58
  <a href="<?php echo admin_action_url( 'remove_exclude_rule', array(
59
  'hmbkp_remove_exclude' => $exclude,
60
  'hmbkp_schedule_id' => $schedule->get_id(),
61
- ) ); ?>" class="delete-action"><?php _e( 'Stop excluding', 'backupwordpress' ); ?></a>
 
 
62
 
63
  <?php endif; ?>
64
 
@@ -72,32 +79,40 @@ $user_excludes = $excludes->get_user_excludes(); ?>
72
 
73
  </table>
74
 
75
- <h3 id="directory-listing"><?php _e( 'Your Site', 'backupwordpress' ); ?></h3>
 
 
76
 
77
- <p><?php _e( 'Here\'s a directory listing of all files on your site, you can browse through and exclude files or folders that you don\'t want included in your backup.', 'backupwordpress' ); ?></p>
 
 
78
 
79
  <?php
80
 
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
 
96
- $site_size = new Site_Size( 'file' );
97
  $excluded_site_size = new Site_Size( 'file', $excludes );
98
 
99
- // Kick off a recursive filesize scan
100
- $files = list_directory_by_total_filesize( $directory, $excludes ); ?>
 
101
 
102
  <table class="widefat">
103
 
@@ -105,11 +120,11 @@ $user_excludes = $excludes->get_user_excludes(); ?>
105
 
106
  <tr>
107
  <th></th>
108
- <th scope="col"><?php _e( 'Name', 'backupwordpress' ); ?></th>
109
- <th scope="col" class="column-format"><?php _e( 'Included Size', 'backupwordpress' ); ?></th>
110
- <th scope="col" class="column-format"><?php _e( 'Permissions', 'backupwordpress' ); ?></th>
111
- <th scope="col" class="column-format"><?php _e( 'Type', 'backupwordpress' ); ?></th>
112
- <th scope="col" class="column-format"><?php _e( 'Status', 'backupwordpress' ); ?></th>
113
  </tr>
114
 
115
  <tr>
@@ -122,14 +137,22 @@ $user_excludes = $excludes->get_user_excludes(); ?>
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; ?>
@@ -152,15 +175,25 @@ $user_excludes = $excludes->get_user_excludes(); ?>
152
 
153
  <?php else :
154
 
155
- $root = new \SplFileInfo( Path::get_root() );
156
-
157
- $size = $site_size->filesize( $root );
158
- $excluded_size = $excluded_site_size->filesize( $root ); ?>
 
159
 
160
  <code>
161
- <?php $excluded_size = is_same_size_format( $size, $excluded_size ) ? (int) size_format( $excluded_size ) : size_format( $excluded_size ); ?>
162
- <?php echo sprintf( __( '%s of %s', 'backupwordpress' ), esc_html( $excluded_size ), esc_html( size_format( $size ) ) ); ?>
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; ?>
@@ -174,9 +207,9 @@ $user_excludes = $excludes->get_user_excludes(); ?>
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>
@@ -197,15 +230,19 @@ $user_excludes = $excludes->get_user_excludes(); ?>
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
 
@@ -231,15 +268,23 @@ $user_excludes = $excludes->get_user_excludes(); ?>
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
 
@@ -253,16 +298,24 @@ $user_excludes = $excludes->get_user_excludes(); ?>
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; ?>
@@ -274,7 +327,8 @@ $user_excludes = $excludes->get_user_excludes(); ?>
274
  <code>--</code>
275
 
276
  <?php endif;
277
- endif; ?>
 
278
 
279
  </td>
280
 
@@ -291,11 +345,13 @@ $user_excludes = $excludes->get_user_excludes(); ?>
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>
@@ -304,26 +360,36 @@ $user_excludes = $excludes->get_user_excludes(); ?>
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
 
@@ -336,7 +402,9 @@ $user_excludes = $excludes->get_user_excludes(); ?>
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; ?>
@@ -346,7 +414,9 @@ $user_excludes = $excludes->get_user_excludes(); ?>
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>
351
 
352
  </div>
2
 
3
  namespace HM\BackUpWordPress;
4
 
5
+ $excludes = $schedule->get_excludes();
6
  $user_excludes = $excludes->get_user_excludes(); ?>
7
 
8
  <div class="hmbkp-exclude-settings">
9
 
10
  <h3>
11
+ <?php esc_html_e( 'Currently Excluded', 'backupwordpress' ); ?>
12
  </h3>
13
 
14
+ <p>
15
+ <?php esc_html_e( 'We automatically detect and ignore common Version Control Systems folders and other backup plugin folders.', 'backupwordpress' ); ?>
16
+ </p>
17
 
18
  <table class="widefat">
19
 
47
 
48
  <td>
49
 
50
+ <?php if (
51
+ ( in_array( $exclude, $excludes->get_default_excludes() ) ) ||
52
+ ( Path::get_path() === trailingslashit( Path::get_root() ) . untrailingslashit( $exclude ) )
53
+ ) : ?>
54
 
55
+ <?php esc_html_e( 'Default rule', 'backupwordpress' ); ?>
56
 
57
  <?php elseif ( defined( 'HMBKP_EXCLUDE' ) && false !== strpos( HMBKP_EXCLUDE, $exclude ) ) : ?>
58
 
59
+ <?php printf( esc_html__( 'Defined in %s', 'backupwordpress' ), 'wp-config.php' ); ?>
60
 
61
  <?php else : ?>
62
 
63
  <a href="<?php echo admin_action_url( 'remove_exclude_rule', array(
64
  'hmbkp_remove_exclude' => $exclude,
65
  'hmbkp_schedule_id' => $schedule->get_id(),
66
+ ) ); ?>" class="delete-action">
67
+ <?php esc_html_e( 'Stop excluding', 'backupwordpress' ); ?>
68
+ </a>
69
 
70
  <?php endif; ?>
71
 
79
 
80
  </table>
81
 
82
+ <h3 id="directory-listing">
83
+ <?php esc_html_e( 'Your Site', 'backupwordpress' ); ?>
84
+ </h3>
85
 
86
+ <p>
87
+ <?php esc_html_e( 'Here\'s a directory listing of all files on your site, you can browse through and exclude files or folders that you don\'t want included in your backup.', 'backupwordpress' ); ?>
88
+ </p>
89
 
90
  <?php
91
 
92
+ // The directory to display.
93
  $directory = Path::get_root();
94
 
95
+ if ( isset( $_GET['hmbkp_directory_browse'] ) ) {
96
 
97
  $untrusted_directory = urldecode( $_GET['hmbkp_directory_browse'] );
98
 
99
+ // Only allow real sub directories of the site root to be browsed.
100
+ if (
101
+ false !== strpos( $untrusted_directory, Path::get_root() ) &&
102
+ is_dir( $untrusted_directory )
103
+ ) {
104
  $directory = $untrusted_directory;
105
+ }
106
+ }
107
 
108
  $exclude_string = implode( '|', $excludes->get_excludes_for_regex() );
109
 
110
+ $site_size = new Site_Size( 'file' );
111
  $excluded_site_size = new Site_Size( 'file', $excludes );
112
 
113
+ // Kick off a recursive filesize scan.
114
+ $files = list_directory_by_total_filesize( $directory, $excludes );
115
+ ?>
116
 
117
  <table class="widefat">
118
 
120
 
121
  <tr>
122
  <th></th>
123
+ <th scope="col"><?php esc_html_e( 'Name', 'backupwordpress' ); ?></th>
124
+ <th scope="col" class="column-format"><?php esc_html_e( 'Included Size', 'backupwordpress' ); ?></th>
125
+ <th scope="col" class="column-format"><?php esc_html_e( 'Permissions', 'backupwordpress' ); ?></th>
126
+ <th scope="col" class="column-format"><?php esc_html_e( 'Type', 'backupwordpress' ); ?></th>
127
+ <th scope="col" class="column-format"><?php esc_html_e( 'Status', 'backupwordpress' ); ?></th>
128
  </tr>
129
 
130
  <tr>
137
 
138
  <?php if ( Path::get_root() !== $directory ) : ?>
139
 
140
+ <a href="<?php echo esc_url( remove_query_arg( 'hmbkp_directory_browse' ) ); ?>">
141
+ <?php echo esc_html( Path::get_root() ); ?>
142
+ </a>
143
  <code>/</code>
144
 
145
+ <?php
146
+ $parents = array_filter( explode(
147
+ '/',
148
+ str_replace( trailingslashit( Path::get_root() ), '', trailingslashit( dirname( $directory ) ) )
149
+ ) );
150
 
151
  foreach ( $parents as $directory_basename ) : ?>
152
 
153
+ <a href="<?php echo esc_url( add_query_arg( 'hmbkp_directory_browse', urlencode( substr( $directory, 0, strpos( $directory, $directory_basename ) ) . $directory_basename ) ) ); ?>">
154
+ <?php echo esc_html( $directory_basename ); ?>
155
+ </a>
156
  <code>/</code>
157
 
158
  <?php endforeach; ?>
175
 
176
  <?php else :
177
 
178
+ $root = new \SplFileInfo( Path::get_root() );
179
+ $size = $site_size->filesize( $root );
180
+ $excluded_size = $excluded_site_size->filesize( $root );
181
+ $excluded_size = is_same_size_format( $size, $excluded_size ) ? (int) size_format( $excluded_size ) : size_format( $excluded_size );
182
+ ?>
183
 
184
  <code>
185
+ <?php
186
+ /* translators: 1: Excluded size 2: Overall site size */
187
+ printf(
188
+ esc_html__( '%1$s of %2$s', 'backupwordpress' ),
189
+ esc_html( $excluded_size ),
190
+ esc_html( size_format( $size ) )
191
+ );
192
+ ?>
193
+
194
+ <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' ) ); ?>">
195
+ <span><?php esc_html_e( 'Refresh', 'backupwordpress' ); ?></span>
196
+ </a>
197
  </code>
198
 
199
  <?php endif; ?>
207
  <code>
208
 
209
  <?php if ( is_link( Path::get_root() ) ) :
210
+ esc_html_e( 'Symlink', 'backupwordpress' );
211
  elseif ( is_dir( Path::get_root() ) ) :
212
+ esc_html_e( 'Folder', 'backupwordpress' );
213
  endif; ?>
214
 
215
  </code>
230
 
231
  $is_excluded = $is_unreadable = false;
232
 
233
+ // Check if the file is excluded.
234
+ if (
235
+ $exclude_string &&
236
+ preg_match( '(' . $exclude_string . ')', str_ireplace( trailingslashit( Path::get_root() ), '', wp_normalize_path( $file->getPathname() ) ) )
237
+ ) :
238
  $is_excluded = true;
239
  endif;
240
 
241
+ // Skip unreadable files.
242
  if ( ! @realpath( $file->getPathname() ) || ! $file->isReadable() ) :
243
  $is_unreadable = true;
244
+ endif;
245
+ ?>
246
 
247
  <tr>
248
 
268
 
269
  <?php if ( $is_unreadable ) : ?>
270
 
271
+ <code class="strikethrough" title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>">
272
+ <?php echo esc_html( $file->getBasename() ); ?>
273
+ </code>
274
 
275
  <?php elseif ( $file->isFile() ) : ?>
276
 
277
+ <code title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>">
278
+ <?php echo esc_html( $file->getBasename() ); ?>
279
+ </code>
280
 
281
  <?php elseif ( $file->isDir() ) : ?>
282
 
283
+ <code title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>">
284
+ <a href="<?php echo esc_url( add_query_arg( 'hmbkp_directory_browse', urlencode( wp_normalize_path( $file->getPathname() ) ) ) ); ?>">
285
+ <?php echo esc_html( $file->getBasename() ); ?>
286
+ </a>
287
+ </code>
288
 
289
  <?php endif; ?>
290
 
298
  $size = $site_size->filesize( $file );
299
 
300
  if ( false !== $size ) :
301
+ $size = $size ?: '0';
302
+ $excluded_size = $excluded_site_size->filesize( $file ) ?: '0'; ?>
303
 
304
  <code>
305
 
306
  <?php if ( $file->isDir() ) :
307
+
308
  $excluded_size = is_same_size_format( $size, $excluded_size ) ? (int) size_format( $excluded_size ) : size_format( $excluded_size );
309
+
310
+ /* translators: 1: Excluded size 2: Overall site size */
311
+ printf(
312
+ esc_html__( '%1$s of %2$s', 'backupwordpress' ),
313
+ esc_html( $excluded_size ),
314
+ esc_html( size_format( $size ) )
315
+ );
316
+
317
  elseif ( ! $is_unreadable ) :
318
+ echo esc_html( size_format( $size ) );
319
  else :
320
  echo '-';
321
  endif; ?>
327
  <code>--</code>
328
 
329
  <?php endif;
330
+ endif;
331
+ ?>
332
 
333
  </td>
334
 
345
  <td>
346
  <code>
347
  <?php if ( $file->isLink() ) : ?>
348
+ <span title="<?php echo esc_attr( wp_normalize_path( $file->getRealPath() ) ); ?>">
349
+ <?php esc_html_e( 'Symlink', 'backupwordpress' ); ?>
350
+ </span>
351
  <?php elseif ( $file->isDir() ) :
352
+ esc_html_e( 'Folder', 'backupwordpress' );
353
  else :
354
+ esc_html_e( 'File', 'backupwordpress' );
355
  endif; ?>
356
  </code>
357
  </td>
360
 
361
  <?php if ( $is_unreadable ) : ?>
362
 
363
+ <strong title="<?php esc_attr_e( 'Unreadable files won\'t be backed up.', 'backupwordpress' ); ?>">
364
+ <?php esc_html_e( 'Unreadable', 'backupwordpress' ); ?>
365
+ </strong>
366
 
367
  <?php elseif ( $is_excluded ) : ?>
368
 
369
+ <strong><?php esc_html_e( 'Excluded', 'backupwordpress' ); ?></strong>
370
 
371
  <?php else :
372
 
373
  $exclude_path = $file->getPathname();
374
 
375
+ // Excluded directories need to be trailingslashed.
376
  if ( $file->isDir() ) :
377
  $exclude_path = trailingslashit( wp_normalize_path( $file->getPathname() ) );
378
  endif; ?>
379
 
380
+ <a href="<?php echo esc_url( wp_nonce_url(
381
+ add_query_arg( array(
382
+ 'hmbkp_schedule_id' => $schedule->get_id(),
383
+ 'action' => 'hmbkp_add_exclude_rule',
384
+ 'hmbkp_exclude_pathname' => urlencode( $exclude_path ),
385
+ ),
386
+ admin_url( 'admin-post.php' )
387
+ ),
388
+ 'hmbkp-add-exclude-rule',
389
+ 'hmbkp-add-exclude-rule-nonce'
390
+ ) ); ?>" class="button-secondary">
391
+ <?php esc_html_e( 'Exclude &rarr;', 'backupwordpress' ); ?>
392
+ </a>
393
 
394
  <?php endif; ?>
395
 
402
  <?php else : ?>
403
 
404
  <tr>
405
+ <td colspan="5">
406
+ <span class="description"><?php esc_html_e( 'This folder is empty', 'backupwordpress' ); ?></span>
407
+ </td>
408
  </tr>
409
 
410
  <?php endif; ?>
414
  </table>
415
 
416
  <p class="submit">
417
+ <a href="<?php echo esc_url( get_settings_url() ) ?>" class="button-primary">
418
+ <?php esc_html_e( 'Done', 'backupwordpress' ); ?>
419
+ </a>
420
  </p>
421
 
422
  </div>
assets/hmbkp.min.js CHANGED
@@ -1,2 +1,24 @@
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);
1
+ var BackUpWordPressAdmin=function(a){"use strict";function b(){d=a("select#hmbkp_schedule_recurrence_type"),
2
+ // Don't ever cache ajax requests
3
+ 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"})}),
4
+ // Show delete confirm message for delete schedule
5
+ a(document).on("click",".hmbkp-schedule-actions .delete-action",function(a){confirm(hmbkp.delete_schedule)||a.preventDefault()}),
6
+ // Show delete confirm message for delete backup
7
+ a(document).on("click",".hmbkp_manage_backups_row .delete-action",function(a){confirm(hmbkp.delete_backup)||a.preventDefault()}),
8
+ // Show delete confirm message for remove exclude rule
9
+ a(document).on("click",".hmbkp-edit-schedule-excludes-form .delete-action",function(a){confirm(hmbkp.remove_exclude_rule)||a.preventDefault()}),
10
+ // Test the cron response using ajax
11
+ a.post(ajaxurl,{nonce:hmbkp.nonce,action:"hmbkp_cron_test"},function(b){"1"!==b&&a(".wrap > h2").after(b)}),
12
+ // Run a backup
13
+ 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()}),
14
+ // Send the schedule id with the heartbeat
15
+ 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"}),
16
+ // Update schedule status on heartbeat tick
17
+ a(document).on("heartbeat-tick",function(b,c){if(
18
+ // If the schedule has finished then reload the page
19
+ 0!==c.hmbkp_schedule_status||a(".hmbkp-error").length||location.reload(!0),
20
+ // If the schedule is still running then update the schedule status
21
+ 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)}}),
22
+ // Closing ThickBox Modal Window
23
+ 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
24
  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.6.1
7
  Author: Human Made Limited
8
  Author URI: http://hmn.md/
9
  License: GPL-2+
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.2
7
  Author: Human Made Limited
8
  Author URI: http://hmn.md/
9
  License: GPL-2+
classes/backup/class-backup-engine-database-mysqldump.php CHANGED
@@ -78,42 +78,6 @@ class Mysqldump_Database_Backup_Engine extends Database_Backup_Engine {
78
 
79
  }
80
 
81
- /**
82
- * Check whether it's possible to connect to the database with the
83
- * credentials we have.
84
- *
85
- * @return bool Whether the database connection was successful.
86
- */
87
- public function check_user_can_connect_to_database_via_cli() {
88
-
89
- if ( ! function_exists( 'proc_open' ) || ! function_exists( 'proc_close' ) ) {
90
- return false;
91
- }
92
-
93
- $args = $this->get_mysql_connection_args();
94
- $args[] = escapeshellarg( $this->get_name() );
95
-
96
- // Quit immediately as we're only interesting in testing the connection
97
- $args[] = '--execute="quit"';
98
-
99
- $process = new Process( 'mysql ' . implode( ' ', $args ) );
100
-
101
- try {
102
- $process->run();
103
- } catch ( \Exception $e ) {
104
- $this->error( __CLASS__, $e->getMessage() );
105
- return false;
106
- }
107
-
108
- if ( ! $process->isSuccessful() ) {
109
- $this->error( __CLASS__, $process->getErrorOutput() );
110
- return false;
111
- }
112
-
113
- return true;
114
-
115
- }
116
-
117
  /**
118
  * Perform the database backup.
119
  *
@@ -121,7 +85,7 @@ class Mysqldump_Database_Backup_Engine extends Database_Backup_Engine {
121
  */
122
  public function backup() {
123
 
124
- if ( ! $this->check_user_can_connect_to_database_via_cli() || ! $this->get_mysqldump_executable_path() ) {
125
  return false;
126
  }
127
 
78
 
79
  }
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  /**
82
  * Perform the database backup.
83
  *
85
  */
86
  public function backup() {
87
 
88
+ if ( ! $this->get_mysqldump_executable_path() ) {
89
  return false;
90
  }
91
 
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.6.1';
10
 
11
  /**
12
  * @var Plugin The singleton instance.
@@ -128,7 +128,8 @@ final class Plugin {
128
 
129
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-notices.php' );
130
 
131
- // Load the admin menu
 
132
  require_once( HMBKP_PLUGIN_PATH . 'admin/menu.php' );
133
  require_once( HMBKP_PLUGIN_PATH . 'admin/actions.php' );
134
 
6
  * Class Plugin
7
  */
8
  final class Plugin {
9
+ const PLUGIN_VERSION = '3.6.2';
10
 
11
  /**
12
  * @var Plugin The singleton instance.
128
 
129
  require_once( HMBKP_PLUGIN_PATH . 'classes/class-notices.php' );
130
 
131
+ // Load Whitelist HTML submodule and admin required functions.
132
+ require_once( HMBKP_PLUGIN_PATH . 'whitelist-html/whitelist-html.php' );
133
  require_once( HMBKP_PLUGIN_PATH . 'admin/menu.php' );
134
  require_once( HMBKP_PLUGIN_PATH . 'admin/actions.php' );
135
 
classes/class-scheduled-backup.php CHANGED
@@ -648,6 +648,9 @@ class Scheduled_Backup {
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
 
653
  }
@@ -665,6 +668,9 @@ class Scheduled_Backup {
665
  // Delete the schedule options
666
  delete_option( 'hmbkp_schedule_' . $this->get_id() );
667
 
 
 
 
668
  // Clear any existing schedules
669
  $this->unschedule();
670
 
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
+ // Delete the schedule cache.
653
+ delete_transient( 'hmbkp_schedules' );
654
  }
655
 
656
  }
668
  // Delete the schedule options
669
  delete_option( 'hmbkp_schedule_' . $this->get_id() );
670
 
671
+ // Delete the schedule cache.
672
+ delete_transient( 'hmbkp_schedules' );
673
+
674
  // Clear any existing schedules
675
  $this->unschedule();
676
 
classes/class-schedules.php CHANGED
@@ -40,10 +40,17 @@ class Schedules {
40
 
41
  public function refresh_schedules() {
42
 
43
- global $wpdb;
44
 
45
- // Load all schedule options from the database
46
- $schedules = $wpdb->get_col( "SELECT option_name from $wpdb->options WHERE option_name LIKE 'hmbkp\_schedule\_%'" );
 
 
 
 
 
 
 
47
 
48
  // Instantiate each one as a Scheduled_Backup
49
  $this->schedules = array_map( array( $this, 'instantiate' ), array_filter( (array) $schedules ) );
40
 
41
  public function refresh_schedules() {
42
 
43
+ $schedules = get_transient( 'hmbkp_schedules' );
44
 
45
+ if ( ! $schedules ) {
46
+
47
+ global $wpdb;
48
+
49
+ // Load all schedule options from the database.
50
+ $schedules = $wpdb->get_col( "SELECT option_name from $wpdb->options WHERE option_name LIKE 'hmbkp\_schedule\_%'" );
51
+
52
+ set_transient( 'hmbkp_schedules', $schedules, WEEK_IN_SECONDS );
53
+ }
54
 
55
  // Instantiate each one as a Scheduled_Backup
56
  $this->schedules = array_map( array( $this, 'instantiate' ), array_filter( (array) $schedules ) );
classes/class-site-size.php CHANGED
@@ -50,11 +50,19 @@ class Site_Size {
50
  // Include database size except for file only schedule.
51
  if ( 'file' !== $this->type ) {
52
 
53
- global $wpdb;
54
- $tables = $wpdb->get_results( 'SHOW TABLE STATUS FROM `' . DB_NAME . '`', ARRAY_A );
55
 
56
- foreach ( $tables as $table ) {
57
- $size += (float) $table['Data_length'];
 
 
 
 
 
 
 
 
 
58
  }
59
  }
60
 
@@ -185,6 +193,15 @@ class Site_Size {
185
 
186
  public function directory_filesize( \SplFileInfo $file ) {
187
 
 
 
 
 
 
 
 
 
 
188
  // If we haven't calculated the site size yet then kick it off in a thread
189
  $directory_sizes = $this->get_cached_filesizes();
190
 
@@ -195,7 +212,10 @@ class Site_Size {
195
  return null;
196
  }
197
 
198
- // The filepaths are stored in keys so we need to flip for use with preg_grep
 
 
 
199
  $directory_sizes = array_flip( preg_grep( '(' . wp_normalize_path( $file->getRealPath() ) . ')', array_flip( $directory_sizes ) ) );
200
 
201
  if ( $this->excludes ) {
@@ -206,8 +226,15 @@ class Site_Size {
206
  }
207
  }
208
 
209
- // Directory size is now just a sum of all files across all sub directories
210
- return absint( array_sum( $directory_sizes ) );
 
 
 
 
 
 
 
211
 
212
  }
213
 
50
  // Include database size except for file only schedule.
51
  if ( 'file' !== $this->type ) {
52
 
53
+ $size = (int) get_transient( 'hmbkp_database_size' );
 
54
 
55
+ if ( ! $size ) {
56
+
57
+ global $wpdb;
58
+
59
+ $tables = $wpdb->get_results( 'SHOW TABLE STATUS FROM `' . DB_NAME . '`', ARRAY_A );
60
+
61
+ foreach ( $tables as $table ) {
62
+ $size += (float) $table['Data_length'];
63
+ }
64
+
65
+ set_transient( 'hmbkp_database_size', $size, WEEK_IN_SECONDS );
66
  }
67
  }
68
 
193
 
194
  public function directory_filesize( \SplFileInfo $file ) {
195
 
196
+ // For performance reasons we cache the root.
197
+ if ( $file->getRealPath() === PATH::get_root() && $this->excludes ) {
198
+
199
+ $directory_sizes = get_transient( 'hmbkp_root_size' );
200
+ if ( $directory_sizes ) {
201
+ return $directory_sizes;
202
+ }
203
+ }
204
+
205
  // If we haven't calculated the site size yet then kick it off in a thread
206
  $directory_sizes = $this->get_cached_filesizes();
207
 
212
  return null;
213
  }
214
 
215
+ /*
216
+ * Ensure we only include files in the current path, the filepaths are stored in keys
217
+ * so we need to flip for use with preg_grep.
218
+ */
219
  $directory_sizes = array_flip( preg_grep( '(' . wp_normalize_path( $file->getRealPath() ) . ')', array_flip( $directory_sizes ) ) );
220
 
221
  if ( $this->excludes ) {
226
  }
227
  }
228
 
229
+ $directory_sizes = absint( array_sum( $directory_sizes ) );
230
+
231
+ // For performance reasons we cache the root.
232
+ if ( $file->getRealPath() === PATH::get_root() && $this->excludes ) {
233
+ set_transient( 'hmbkp_root_size', $directory_sizes, DAY_IN_SECONDS );
234
+ }
235
+
236
+ // Directory size is now just a sum of all files across all sub directories.
237
+ return $directory_sizes;
238
 
239
  }
240
 
composer.lock CHANGED
@@ -61,16 +61,16 @@
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,20 +106,20 @@
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,7 +155,7 @@
155
  ],
156
  "description": "Symfony Process Component",
157
  "homepage": "https://symfony.com",
158
- "time": "2016-03-23 13:11:46"
159
  }
160
  ],
161
  "packages-dev": [],
61
  },
62
  {
63
  "name": "symfony/finder",
64
+ "version": "v2.8.9",
65
  "source": {
66
  "type": "git",
67
  "url": "https://github.com/symfony/finder.git",
68
+ "reference": "60804d88691e4a73bbbb3035eb1d9f075c5c2c10"
69
  },
70
  "dist": {
71
  "type": "zip",
72
+ "url": "https://api.github.com/repos/symfony/finder/zipball/60804d88691e4a73bbbb3035eb1d9f075c5c2c10",
73
+ "reference": "60804d88691e4a73bbbb3035eb1d9f075c5c2c10",
74
  "shasum": ""
75
  },
76
  "require": {
106
  ],
107
  "description": "Symfony Finder Component",
108
  "homepage": "https://symfony.com",
109
+ "time": "2016-07-26 08:02:44"
110
  },
111
  {
112
  "name": "symfony/process",
113
+ "version": "v2.8.9",
114
  "source": {
115
  "type": "git",
116
  "url": "https://github.com/symfony/process.git",
117
+ "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c"
118
  },
119
  "dist": {
120
  "type": "zip",
121
+ "url": "https://api.github.com/repos/symfony/process/zipball/d20332e43e8774ff8870b394f3dd6020cc7f8e0c",
122
+ "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c",
123
  "shasum": ""
124
  },
125
  "require": {
155
  ],
156
  "description": "Symfony Process Component",
157
  "homepage": "https://symfony.com",
158
+ "time": "2016-07-28 11:13:19"
159
  }
160
  ],
161
  "packages-dev": [],
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.6.1\n"
6
  "Report-Msgid-Bugs-To: backupwordpress@hmn.md\n"
7
- "POT-Creation-Date: 2016-04-26 15:47:53+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -67,18 +67,18 @@ msgid ""
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, "
@@ -90,7 +90,7 @@ msgstr ""
90
  msgid "Size"
91
  msgstr ""
92
 
93
- #: admin/backups-table.php:15 admin/schedule-form-excludes.php:111
94
  msgid "Type"
95
  msgstr ""
96
 
@@ -488,92 +488,93 @@ msgstr ""
488
  msgid "Currently Excluded"
489
  msgstr ""
490
 
491
- #: admin/schedule-form-excludes.php:14
492
  msgid ""
493
- "We automatically detect and ignore common <abbr title=\"Version Control "
494
- "Systems\">VCS</abbr> folders and other backup plugin folders."
495
  msgstr ""
496
 
497
- #: admin/schedule-form-excludes.php:50
498
  msgid "Default rule"
499
  msgstr ""
500
 
501
- #: admin/schedule-form-excludes.php:54
502
- msgid "Defined in wp-config.php"
503
  msgstr ""
504
 
505
- #: admin/schedule-form-excludes.php:61
506
  msgid "Stop excluding"
507
  msgstr ""
508
 
509
- #: admin/schedule-form-excludes.php:75
510
  msgid "Your Site"
511
  msgstr ""
512
 
513
- #: admin/schedule-form-excludes.php:77
514
  msgid ""
515
  "Here's a directory listing of all files on your site, you can browse "
516
  "through and exclude files or folders that you don't want included in your "
517
  "backup."
518
  msgstr ""
519
 
520
- #: admin/schedule-form-excludes.php:108
521
  msgid "Name"
522
  msgstr ""
523
 
524
- #: admin/schedule-form-excludes.php:109
525
  msgid "Included Size"
526
  msgstr ""
527
 
528
- #: admin/schedule-form-excludes.php:110
529
  msgid "Permissions"
530
  msgstr ""
531
 
532
- #: admin/schedule-form-excludes.php:112
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
 
540
- #: admin/schedule-form-excludes.php:163
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 ""
@@ -869,41 +870,41 @@ msgstr ""
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 ""
@@ -911,7 +912,7 @@ msgid ""
911
  "extensions?%2$s"
912
  msgstr ""
913
 
914
- #: classes/class-plugin.php:454
915
  msgid "Dismiss this notice."
916
  msgstr ""
917
 
2
  # This file is distributed under the GPL-2+.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: BackUpWordPress 3.6.2\n"
6
  "Report-Msgid-Bugs-To: backupwordpress@hmn.md\n"
7
+ "POT-Creation-Date: 2016-08-02 13:42:15+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
67
  "free."
68
  msgstr ""
69
 
70
+ #: admin/actions.php:638 admin/actions.php:644
71
  msgid "BackUpWordPress has detected a problem."
72
  msgstr ""
73
 
74
+ #: admin/actions.php:638
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:644
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, "
90
  msgid "Size"
91
  msgstr ""
92
 
93
+ #: admin/backups-table.php:15 admin/schedule-form-excludes.php:126
94
  msgid "Type"
95
  msgstr ""
96
 
488
  msgid "Currently Excluded"
489
  msgstr ""
490
 
491
+ #: admin/schedule-form-excludes.php:15
492
  msgid ""
493
+ "We automatically detect and ignore common Version Control Systems folders "
494
+ "and other backup plugin folders."
495
  msgstr ""
496
 
497
+ #: admin/schedule-form-excludes.php:55
498
  msgid "Default rule"
499
  msgstr ""
500
 
501
+ #: admin/schedule-form-excludes.php:59
502
+ msgid "Defined in %s"
503
  msgstr ""
504
 
505
+ #: admin/schedule-form-excludes.php:67
506
  msgid "Stop excluding"
507
  msgstr ""
508
 
509
+ #: admin/schedule-form-excludes.php:83
510
  msgid "Your Site"
511
  msgstr ""
512
 
513
+ #: admin/schedule-form-excludes.php:87
514
  msgid ""
515
  "Here's a directory listing of all files on your site, you can browse "
516
  "through and exclude files or folders that you don't want included in your "
517
  "backup."
518
  msgstr ""
519
 
520
+ #: admin/schedule-form-excludes.php:123
521
  msgid "Name"
522
  msgstr ""
523
 
524
+ #: admin/schedule-form-excludes.php:124
525
  msgid "Included Size"
526
  msgstr ""
527
 
528
+ #: admin/schedule-form-excludes.php:125
529
  msgid "Permissions"
530
  msgstr ""
531
 
532
+ #: admin/schedule-form-excludes.php:127
533
  msgid "Status"
534
  msgstr ""
535
 
536
+ #: admin/schedule-form-excludes.php:188 admin/schedule-form-excludes.php:312
537
+ #. translators: 1: Excluded size 2: Overall site size
538
+ msgid "%1$s of %2$s"
539
  msgstr ""
540
 
541
+ #: admin/schedule-form-excludes.php:195
542
  msgid "Refresh"
543
  msgstr ""
544
 
545
+ #: admin/schedule-form-excludes.php:210 admin/schedule-form-excludes.php:349
546
  msgid "Symlink"
547
  msgstr ""
548
 
549
+ #: admin/schedule-form-excludes.php:212 admin/schedule-form-excludes.php:352
550
  msgid "Folder"
551
  msgstr ""
552
 
553
+ #: admin/schedule-form-excludes.php:354
554
  msgid "File"
555
  msgstr ""
556
 
557
+ #: admin/schedule-form-excludes.php:363
558
  msgid "Unreadable files won't be backed up."
559
  msgstr ""
560
 
561
+ #: admin/schedule-form-excludes.php:364
562
  msgid "Unreadable"
563
  msgstr ""
564
 
565
+ #: admin/schedule-form-excludes.php:369
566
  msgid "Excluded"
567
  msgstr ""
568
 
569
+ #: admin/schedule-form-excludes.php:391
570
  msgid "Exclude &rarr;"
571
  msgstr ""
572
 
573
+ #: admin/schedule-form-excludes.php:406
574
  msgid "This folder is empty"
575
  msgstr ""
576
 
577
+ #: admin/schedule-form-excludes.php:418 admin/schedule-form.php:204
578
  #: admin/schedule-settings.php:85
579
  msgid "Done"
580
  msgstr ""
870
  msgid "This %s file ensures that other people cannot download your backup files."
871
  msgstr ""
872
 
873
+ #: classes/class-plugin.php:241
874
  msgid "Update"
875
  msgstr ""
876
 
877
+ #: classes/class-plugin.php:242
878
  msgid "Cancel"
879
  msgstr ""
880
 
881
+ #: classes/class-plugin.php:243
882
  msgid ""
883
  "Are you sure you want to delete this schedule? All of its backups will also "
884
  "be deleted."
885
  msgstr ""
886
 
887
+ #: classes/class-plugin.php:243 classes/class-plugin.php:244
888
+ #: classes/class-plugin.php:245 classes/class-plugin.php:246
889
  msgid "'Cancel' to go back, 'OK' to delete."
890
  msgstr ""
891
 
892
+ #: classes/class-plugin.php:244
893
  msgid "Are you sure you want to delete this backup?"
894
  msgstr ""
895
 
896
+ #: classes/class-plugin.php:245
897
  msgid "Are you sure you want to remove this exclude rule?"
898
  msgstr ""
899
 
900
+ #: classes/class-plugin.php:246
901
  msgid ""
902
  "Reducing the number of backups that are stored on this server will cause "
903
  "some of your existing backups to be deleted. Are you sure that's what you "
904
  "want?"
905
  msgstr ""
906
 
907
+ #: classes/class-plugin.php:445
908
  #. translators: %1$s and %2$s expand to anchor tags linking to the new
909
  #. extensions page.
910
  msgid ""
912
  "extensions?%2$s"
913
  msgstr ""
914
 
915
+ #: classes/class-plugin.php:455
916
  msgid "Dismiss this notice."
917
  msgstr ""
918
 
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === BackUpWordPress ===
2
- Contributors: humanmade, willmot, pauldewouters, joehoyle, mattheu, tcrsavage, cuvelier
3
  Tags: back up, backup, backups, database, zip, db, files, archive, wp-cli, humanmade
4
  Requires at least: 3.9
5
- Tested up to: 4.4.2
6
- Stable tag: 3.6.1
7
 
8
  Simple automated backups of your WordPress-powered website.
9
 
@@ -158,6 +158,16 @@ users should see major improvements to reliability.
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
1
  === BackUpWordPress ===
2
+ Contributors: humanmade, willmot, dashaluna, pauldewouters, joehoyle, mattheu, tcrsavage, cuvelier
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.5
6
+ Stable tag: 3.6.2
7
 
8
  Simple automated backups of your WordPress-powered website.
9
 
158
 
159
  == Changelog ==
160
 
161
+ ### 3.6.2 / 2016-08-02
162
+
163
+ * Improves admin performance.
164
+ * Improves security in internationalised strings.
165
+
166
+ ### 3.6.1 / 2016-04-26
167
+
168
+ * Bug fixes/improvements in disk space calculation
169
+ * Misc bug fixes
170
+
171
  ### 3.6.0 / 2016-03-31
172
 
173
  * Fix a bug caused by using a function incompatible with min PHP version requirements
vendor/composer/autoload_classmap.php CHANGED
@@ -6,69 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
- 'Ifsnop\\Mysqldump\\CompressBzip2' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
10
- 'Ifsnop\\Mysqldump\\CompressGzip' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
11
- 'Ifsnop\\Mysqldump\\CompressManagerFactory' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
12
- 'Ifsnop\\Mysqldump\\CompressMethod' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
13
- 'Ifsnop\\Mysqldump\\CompressNone' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
14
- 'Ifsnop\\Mysqldump\\Mysqldump' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
15
- 'Ifsnop\\Mysqldump\\TypeAdapter' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
16
- 'Ifsnop\\Mysqldump\\TypeAdapterDblib' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
17
- 'Ifsnop\\Mysqldump\\TypeAdapterFactory' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
18
- 'Ifsnop\\Mysqldump\\TypeAdapterMysql' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
19
- 'Ifsnop\\Mysqldump\\TypeAdapterPgsql' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
20
- 'Ifsnop\\Mysqldump\\TypeAdapterSqlite' => $vendorDir . '/ifsnop/mysqldump-php/src/Ifsnop/Mysqldump/Mysqldump.php',
21
- 'Symfony\\Component\\Finder\\Adapter\\AbstractAdapter' => $vendorDir . '/symfony/finder/Adapter/AbstractAdapter.php',
22
- 'Symfony\\Component\\Finder\\Adapter\\AbstractFindAdapter' => $vendorDir . '/symfony/finder/Adapter/AbstractFindAdapter.php',
23
- 'Symfony\\Component\\Finder\\Adapter\\AdapterInterface' => $vendorDir . '/symfony/finder/Adapter/AdapterInterface.php',
24
- 'Symfony\\Component\\Finder\\Adapter\\BsdFindAdapter' => $vendorDir . '/symfony/finder/Adapter/BsdFindAdapter.php',
25
- 'Symfony\\Component\\Finder\\Adapter\\GnuFindAdapter' => $vendorDir . '/symfony/finder/Adapter/GnuFindAdapter.php',
26
- 'Symfony\\Component\\Finder\\Adapter\\PhpAdapter' => $vendorDir . '/symfony/finder/Adapter/PhpAdapter.php',
27
- 'Symfony\\Component\\Finder\\Comparator\\Comparator' => $vendorDir . '/symfony/finder/Comparator/Comparator.php',
28
- 'Symfony\\Component\\Finder\\Comparator\\DateComparator' => $vendorDir . '/symfony/finder/Comparator/DateComparator.php',
29
- 'Symfony\\Component\\Finder\\Comparator\\NumberComparator' => $vendorDir . '/symfony/finder/Comparator/NumberComparator.php',
30
- 'Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/finder/Exception/AccessDeniedException.php',
31
- 'Symfony\\Component\\Finder\\Exception\\AdapterFailureException' => $vendorDir . '/symfony/finder/Exception/AdapterFailureException.php',
32
- 'Symfony\\Component\\Finder\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/finder/Exception/ExceptionInterface.php',
33
- 'Symfony\\Component\\Finder\\Exception\\OperationNotPermitedException' => $vendorDir . '/symfony/finder/Exception/OperationNotPermitedException.php',
34
- 'Symfony\\Component\\Finder\\Exception\\ShellCommandFailureException' => $vendorDir . '/symfony/finder/Exception/ShellCommandFailureException.php',
35
- 'Symfony\\Component\\Finder\\Expression\\Expression' => $vendorDir . '/symfony/finder/Expression/Expression.php',
36
- 'Symfony\\Component\\Finder\\Expression\\Glob' => $vendorDir . '/symfony/finder/Expression/Glob.php',
37
- 'Symfony\\Component\\Finder\\Expression\\Regex' => $vendorDir . '/symfony/finder/Expression/Regex.php',
38
- 'Symfony\\Component\\Finder\\Expression\\ValueInterface' => $vendorDir . '/symfony/finder/Expression/ValueInterface.php',
39
- 'Symfony\\Component\\Finder\\Finder' => $vendorDir . '/symfony/finder/Finder.php',
40
- 'Symfony\\Component\\Finder\\Glob' => $vendorDir . '/symfony/finder/Glob.php',
41
- 'Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => $vendorDir . '/symfony/finder/Iterator/CustomFilterIterator.php',
42
- 'Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DateRangeFilterIterator.php',
43
- 'Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DepthRangeFilterIterator.php',
44
- 'Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => $vendorDir . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php',
45
- 'Symfony\\Component\\Finder\\Iterator\\FilePathsIterator' => $vendorDir . '/symfony/finder/Iterator/FilePathsIterator.php',
46
- 'Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FileTypeFilterIterator.php',
47
- 'Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilecontentFilterIterator.php',
48
- 'Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilenameFilterIterator.php',
49
- 'Symfony\\Component\\Finder\\Iterator\\FilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilterIterator.php',
50
- 'Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php',
51
- 'Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => $vendorDir . '/symfony/finder/Iterator/PathFilterIterator.php',
52
- 'Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php',
53
- 'Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/SizeRangeFilterIterator.php',
54
- 'Symfony\\Component\\Finder\\Iterator\\SortableIterator' => $vendorDir . '/symfony/finder/Iterator/SortableIterator.php',
55
- 'Symfony\\Component\\Finder\\Shell\\Command' => $vendorDir . '/symfony/finder/Shell/Command.php',
56
- 'Symfony\\Component\\Finder\\Shell\\Shell' => $vendorDir . '/symfony/finder/Shell/Shell.php',
57
- 'Symfony\\Component\\Finder\\SplFileInfo' => $vendorDir . '/symfony/finder/SplFileInfo.php',
58
- 'Symfony\\Component\\Process\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/process/Exception/ExceptionInterface.php',
59
- 'Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/process/Exception/InvalidArgumentException.php',
60
- 'Symfony\\Component\\Process\\Exception\\LogicException' => $vendorDir . '/symfony/process/Exception/LogicException.php',
61
- 'Symfony\\Component\\Process\\Exception\\ProcessFailedException' => $vendorDir . '/symfony/process/Exception/ProcessFailedException.php',
62
- 'Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => $vendorDir . '/symfony/process/Exception/ProcessTimedOutException.php',
63
- 'Symfony\\Component\\Process\\Exception\\RuntimeException' => $vendorDir . '/symfony/process/Exception/RuntimeException.php',
64
- 'Symfony\\Component\\Process\\ExecutableFinder' => $vendorDir . '/symfony/process/ExecutableFinder.php',
65
- 'Symfony\\Component\\Process\\PhpExecutableFinder' => $vendorDir . '/symfony/process/PhpExecutableFinder.php',
66
- 'Symfony\\Component\\Process\\PhpProcess' => $vendorDir . '/symfony/process/PhpProcess.php',
67
- 'Symfony\\Component\\Process\\Pipes\\AbstractPipes' => $vendorDir . '/symfony/process/Pipes/AbstractPipes.php',
68
- 'Symfony\\Component\\Process\\Pipes\\PipesInterface' => $vendorDir . '/symfony/process/Pipes/PipesInterface.php',
69
- 'Symfony\\Component\\Process\\Pipes\\UnixPipes' => $vendorDir . '/symfony/process/Pipes/UnixPipes.php',
70
- 'Symfony\\Component\\Process\\Pipes\\WindowsPipes' => $vendorDir . '/symfony/process/Pipes/WindowsPipes.php',
71
- 'Symfony\\Component\\Process\\Process' => $vendorDir . '/symfony/process/Process.php',
72
- 'Symfony\\Component\\Process\\ProcessBuilder' => $vendorDir . '/symfony/process/ProcessBuilder.php',
73
- 'Symfony\\Component\\Process\\ProcessUtils' => $vendorDir . '/symfony/process/ProcessUtils.php',
74
  );
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  );
vendor/composer/installed.json CHANGED
@@ -55,23 +55,23 @@
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,23 +106,23 @@
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": {
55
  },
56
  {
57
  "name": "symfony/finder",
58
+ "version": "v2.8.9",
59
+ "version_normalized": "2.8.9.0",
60
  "source": {
61
  "type": "git",
62
  "url": "https://github.com/symfony/finder.git",
63
+ "reference": "60804d88691e4a73bbbb3035eb1d9f075c5c2c10"
64
  },
65
  "dist": {
66
  "type": "zip",
67
+ "url": "https://api.github.com/repos/symfony/finder/zipball/60804d88691e4a73bbbb3035eb1d9f075c5c2c10",
68
+ "reference": "60804d88691e4a73bbbb3035eb1d9f075c5c2c10",
69
  "shasum": ""
70
  },
71
  "require": {
72
  "php": ">=5.3.9"
73
  },
74
+ "time": "2016-07-26 08:02:44",
75
  "type": "library",
76
  "extra": {
77
  "branch-alias": {
106
  },
107
  {
108
  "name": "symfony/process",
109
+ "version": "v2.8.9",
110
+ "version_normalized": "2.8.9.0",
111
  "source": {
112
  "type": "git",
113
  "url": "https://github.com/symfony/process.git",
114
+ "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c"
115
  },
116
  "dist": {
117
  "type": "zip",
118
+ "url": "https://api.github.com/repos/symfony/process/zipball/d20332e43e8774ff8870b394f3dd6020cc7f8e0c",
119
+ "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c",
120
  "shasum": ""
121
  },
122
  "require": {
123
  "php": ">=5.3.9"
124
  },
125
+ "time": "2016-07-28 11:13:19",
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
@@ -125,9 +125,9 @@ class Expression implements ValueInterface
125
  }
126
 
127
  /**
128
- * @throws \LogicException
129
- *
130
  * @return Glob
 
 
131
  */
132
  public function getGlob()
133
  {
125
  }
126
 
127
  /**
 
 
128
  * @return Glob
129
+ *
130
+ * @throws \LogicException
131
  */
132
  public function getGlob()
133
  {
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
@@ -133,10 +133,10 @@ class Finder implements \IteratorAggregate, \Countable
133
  *
134
  * @param string $name
135
  *
136
- * @throws \InvalidArgumentException
137
- *
138
  * @return Finder The current Finder instance
139
  *
 
 
140
  * @deprecated since 2.8, to be removed in 3.0.
141
  */
142
  public function setAdapter($name)
@@ -192,7 +192,7 @@ class Finder implements \IteratorAggregate, \Countable
192
  /**
193
  * Restricts the matching to directories only.
194
  *
195
- * @return Finder The current Finder instance
196
  */
197
  public function directories()
198
  {
@@ -204,7 +204,7 @@ class Finder implements \IteratorAggregate, \Countable
204
  /**
205
  * Restricts the matching to files only.
206
  *
207
- * @return Finder The current Finder instance
208
  */
209
  public function files()
210
  {
@@ -223,7 +223,7 @@ class Finder implements \IteratorAggregate, \Countable
223
  *
224
  * @param int $level The depth level expression
225
  *
226
- * @return Finder The current Finder instance
227
  *
228
  * @see DepthRangeFilterIterator
229
  * @see NumberComparator
@@ -247,7 +247,7 @@ class Finder implements \IteratorAggregate, \Countable
247
  *
248
  * @param string $date A date range string
249
  *
250
- * @return Finder The current Finder instance
251
  *
252
  * @see strtotime
253
  * @see DateRangeFilterIterator
@@ -271,7 +271,7 @@ class Finder implements \IteratorAggregate, \Countable
271
  *
272
  * @param string $pattern A pattern (a regexp, a glob, or a string)
273
  *
274
- * @return Finder The current Finder instance
275
  *
276
  * @see FilenameFilterIterator
277
  */
@@ -287,7 +287,7 @@ class Finder implements \IteratorAggregate, \Countable
287
  *
288
  * @param string $pattern A pattern (a regexp, a glob, or a string)
289
  *
290
- * @return Finder The current Finder instance
291
  *
292
  * @see FilenameFilterIterator
293
  */
@@ -308,7 +308,7 @@ class Finder implements \IteratorAggregate, \Countable
308
  *
309
  * @param string $pattern A pattern (string or regexp)
310
  *
311
- * @return Finder The current Finder instance
312
  *
313
  * @see FilecontentFilterIterator
314
  */
@@ -329,7 +329,7 @@ class Finder implements \IteratorAggregate, \Countable
329
  *
330
  * @param string $pattern A pattern (string or regexp)
331
  *
332
- * @return Finder The current Finder instance
333
  *
334
  * @see FilecontentFilterIterator
335
  */
@@ -352,7 +352,7 @@ class Finder implements \IteratorAggregate, \Countable
352
  *
353
  * @param string $pattern A pattern (a regexp or a string)
354
  *
355
- * @return Finder The current Finder instance
356
  *
357
  * @see FilenameFilterIterator
358
  */
@@ -375,7 +375,7 @@ class Finder implements \IteratorAggregate, \Countable
375
  *
376
  * @param string $pattern A pattern (a regexp or a string)
377
  *
378
- * @return Finder The current Finder instance
379
  *
380
  * @see FilenameFilterIterator
381
  */
@@ -395,7 +395,7 @@ class Finder implements \IteratorAggregate, \Countable
395
  *
396
  * @param string $size A size range string
397
  *
398
- * @return Finder The current Finder instance
399
  *
400
  * @see SizeRangeFilterIterator
401
  * @see NumberComparator
@@ -412,7 +412,7 @@ class Finder implements \IteratorAggregate, \Countable
412
  *
413
  * @param string|array $dirs A directory path or an array of directories
414
  *
415
- * @return Finder The current Finder instance
416
  *
417
  * @see ExcludeDirectoryFilterIterator
418
  */
@@ -428,7 +428,7 @@ class Finder implements \IteratorAggregate, \Countable
428
  *
429
  * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not
430
  *
431
- * @return Finder The current Finder instance
432
  *
433
  * @see ExcludeDirectoryFilterIterator
434
  */
@@ -448,7 +448,7 @@ class Finder implements \IteratorAggregate, \Countable
448
  *
449
  * @param bool $ignoreVCS Whether to exclude VCS files or not
450
  *
451
- * @return Finder The current Finder instance
452
  *
453
  * @see ExcludeDirectoryFilterIterator
454
  */
@@ -488,7 +488,7 @@ class Finder implements \IteratorAggregate, \Countable
488
  *
489
  * @param \Closure $closure An anonymous function
490
  *
491
- * @return Finder The current Finder instance
492
  *
493
  * @see SortableIterator
494
  */
@@ -504,7 +504,7 @@ class Finder implements \IteratorAggregate, \Countable
504
  *
505
  * This can be slow as all the matching files and directories must be retrieved for comparison.
506
  *
507
- * @return Finder The current Finder instance
508
  *
509
  * @see SortableIterator
510
  */
@@ -520,7 +520,7 @@ class Finder implements \IteratorAggregate, \Countable
520
  *
521
  * This can be slow as all the matching files and directories must be retrieved for comparison.
522
  *
523
- * @return Finder The current Finder instance
524
  *
525
  * @see SortableIterator
526
  */
@@ -538,7 +538,7 @@ class Finder implements \IteratorAggregate, \Countable
538
  *
539
  * This can be slow as all the matching files and directories must be retrieved for comparison.
540
  *
541
- * @return Finder The current Finder instance
542
  *
543
  * @see SortableIterator
544
  */
@@ -558,7 +558,7 @@ class Finder implements \IteratorAggregate, \Countable
558
  *
559
  * This can be slow as all the matching files and directories must be retrieved for comparison.
560
  *
561
- * @return Finder The current Finder instance
562
  *
563
  * @see SortableIterator
564
  */
@@ -576,7 +576,7 @@ class Finder implements \IteratorAggregate, \Countable
576
  *
577
  * This can be slow as all the matching files and directories must be retrieved for comparison.
578
  *
579
- * @return Finder The current Finder instance
580
  *
581
  * @see SortableIterator
582
  */
@@ -595,7 +595,7 @@ class Finder implements \IteratorAggregate, \Countable
595
  *
596
  * @param \Closure $closure An anonymous function
597
  *
598
- * @return Finder The current Finder instance
599
  *
600
  * @see CustomFilterIterator
601
  */
@@ -609,7 +609,7 @@ class Finder implements \IteratorAggregate, \Countable
609
  /**
610
  * Forces the following of symlinks.
611
  *
612
- * @return Finder The current Finder instance
613
  */
614
  public function followLinks()
615
  {
@@ -625,7 +625,7 @@ class Finder implements \IteratorAggregate, \Countable
625
  *
626
  * @param bool $ignore
627
  *
628
- * @return Finder The current Finder instance
629
  */
630
  public function ignoreUnreadableDirs($ignore = true)
631
  {
@@ -639,7 +639,7 @@ class Finder implements \IteratorAggregate, \Countable
639
  *
640
  * @param string|array $dirs A directory path or an array of directories
641
  *
642
- * @return Finder The current Finder instance
643
  *
644
  * @throws \InvalidArgumentException if one of the directories does not exist
645
  */
@@ -667,7 +667,7 @@ class Finder implements \IteratorAggregate, \Countable
667
  *
668
  * This method implements the IteratorAggregate interface.
669
  *
670
- * @return \Iterator An iterator
671
  *
672
  * @throws \LogicException if the in() method has not been called
673
  */
@@ -700,7 +700,7 @@ class Finder implements \IteratorAggregate, \Countable
700
  *
701
  * @param mixed $iterator
702
  *
703
- * @return Finder The finder
704
  *
705
  * @throws \InvalidArgumentException When the given argument is not iterable.
706
  */
133
  *
134
  * @param string $name
135
  *
 
 
136
  * @return Finder The current Finder instance
137
  *
138
+ * @throws \InvalidArgumentException
139
+ *
140
  * @deprecated since 2.8, to be removed in 3.0.
141
  */
142
  public function setAdapter($name)
192
  /**
193
  * Restricts the matching to directories only.
194
  *
195
+ * @return Finder|SplFileInfo[] The current Finder instance
196
  */
197
  public function directories()
198
  {
204
  /**
205
  * Restricts the matching to files only.
206
  *
207
+ * @return Finder|SplFileInfo[] The current Finder instance
208
  */
209
  public function files()
210
  {
223
  *
224
  * @param int $level The depth level expression
225
  *
226
+ * @return Finder|SplFileInfo[] The current Finder instance
227
  *
228
  * @see DepthRangeFilterIterator
229
  * @see NumberComparator
247
  *
248
  * @param string $date A date range string
249
  *
250
+ * @return Finder|SplFileInfo[] The current Finder instance
251
  *
252
  * @see strtotime
253
  * @see DateRangeFilterIterator
271
  *
272
  * @param string $pattern A pattern (a regexp, a glob, or a string)
273
  *
274
+ * @return Finder|SplFileInfo[] The current Finder instance
275
  *
276
  * @see FilenameFilterIterator
277
  */
287
  *
288
  * @param string $pattern A pattern (a regexp, a glob, or a string)
289
  *
290
+ * @return Finder|SplFileInfo[] The current Finder instance
291
  *
292
  * @see FilenameFilterIterator
293
  */
308
  *
309
  * @param string $pattern A pattern (string or regexp)
310
  *
311
+ * @return Finder|SplFileInfo[] The current Finder instance
312
  *
313
  * @see FilecontentFilterIterator
314
  */
329
  *
330
  * @param string $pattern A pattern (string or regexp)
331
  *
332
+ * @return Finder|SplFileInfo[] The current Finder instance
333
  *
334
  * @see FilecontentFilterIterator
335
  */
352
  *
353
  * @param string $pattern A pattern (a regexp or a string)
354
  *
355
+ * @return Finder|SplFileInfo[] The current Finder instance
356
  *
357
  * @see FilenameFilterIterator
358
  */
375
  *
376
  * @param string $pattern A pattern (a regexp or a string)
377
  *
378
+ * @return Finder|SplFileInfo[] The current Finder instance
379
  *
380
  * @see FilenameFilterIterator
381
  */
395
  *
396
  * @param string $size A size range string
397
  *
398
+ * @return Finder|SplFileInfo[] The current Finder instance
399
  *
400
  * @see SizeRangeFilterIterator
401
  * @see NumberComparator
412
  *
413
  * @param string|array $dirs A directory path or an array of directories
414
  *
415
+ * @return Finder|SplFileInfo[] The current Finder instance
416
  *
417
  * @see ExcludeDirectoryFilterIterator
418
  */
428
  *
429
  * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not
430
  *
431
+ * @return Finder|SplFileInfo[] The current Finder instance
432
  *
433
  * @see ExcludeDirectoryFilterIterator
434
  */
448
  *
449
  * @param bool $ignoreVCS Whether to exclude VCS files or not
450
  *
451
+ * @return Finder|SplFileInfo[] The current Finder instance
452
  *
453
  * @see ExcludeDirectoryFilterIterator
454
  */
488
  *
489
  * @param \Closure $closure An anonymous function
490
  *
491
+ * @return Finder|SplFileInfo[] The current Finder instance
492
  *
493
  * @see SortableIterator
494
  */
504
  *
505
  * This can be slow as all the matching files and directories must be retrieved for comparison.
506
  *
507
+ * @return Finder|SplFileInfo[] The current Finder instance
508
  *
509
  * @see SortableIterator
510
  */
520
  *
521
  * This can be slow as all the matching files and directories must be retrieved for comparison.
522
  *
523
+ * @return Finder|SplFileInfo[] The current Finder instance
524
  *
525
  * @see SortableIterator
526
  */
538
  *
539
  * This can be slow as all the matching files and directories must be retrieved for comparison.
540
  *
541
+ * @return Finder|SplFileInfo[] The current Finder instance
542
  *
543
  * @see SortableIterator
544
  */
558
  *
559
  * This can be slow as all the matching files and directories must be retrieved for comparison.
560
  *
561
+ * @return Finder|SplFileInfo[] The current Finder instance
562
  *
563
  * @see SortableIterator
564
  */
576
  *
577
  * This can be slow as all the matching files and directories must be retrieved for comparison.
578
  *
579
+ * @return Finder|SplFileInfo[] The current Finder instance
580
  *
581
  * @see SortableIterator
582
  */
595
  *
596
  * @param \Closure $closure An anonymous function
597
  *
598
+ * @return Finder|SplFileInfo[] The current Finder instance
599
  *
600
  * @see CustomFilterIterator
601
  */
609
  /**
610
  * Forces the following of symlinks.
611
  *
612
+ * @return Finder|SplFileInfo[] The current Finder instance
613
  */
614
  public function followLinks()
615
  {
625
  *
626
  * @param bool $ignore
627
  *
628
+ * @return Finder|SplFileInfo[] The current Finder instance
629
  */
630
  public function ignoreUnreadableDirs($ignore = true)
631
  {
639
  *
640
  * @param string|array $dirs A directory path or an array of directories
641
  *
642
+ * @return Finder|SplFileInfo[] The current Finder instance
643
  *
644
  * @throws \InvalidArgumentException if one of the directories does not exist
645
  */
667
  *
668
  * This method implements the IteratorAggregate interface.
669
  *
670
+ * @return \Iterator|SplFileInfo[] An iterator
671
  *
672
  * @throws \LogicException if the in() method has not been called
673
  */
700
  *
701
  * @param mixed $iterator
702
  *
703
+ * @return Finder|SplFileInfo[] The finder
704
  *
705
  * @throws \InvalidArgumentException When the given argument is not iterable.
706
  */
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
File without changes
vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php CHANGED
File without changes
vendor/symfony/finder/Iterator/PathFilterIterator.php CHANGED
@@ -45,7 +45,7 @@ class PathFilterIterator extends MultiplePcreFilterIterator
45
  *
46
  * Use only / as directory separator (on Windows also).
47
  *
48
- * @param string $str Pattern: regexp or dirname.
49
  *
50
  * @return string regexp corresponding to a given string or regexp
51
  */
45
  *
46
  * Use only / as directory separator (on Windows also).
47
  *
48
+ * @param string $str Pattern: regexp or dirname
49
  *
50
  * @return string regexp corresponding to a given string or regexp
51
  */
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
@@ -22,10 +22,9 @@ abstract class AbstractPipes implements PipesInterface
22
  public $pipes = array();
23
 
24
  /** @var string */
25
- protected $inputBuffer = '';
26
  /** @var resource|null */
27
- protected $input;
28
-
29
  /** @var bool */
30
  private $blocked = true;
31
 
@@ -91,9 +90,8 @@ abstract class AbstractPipes implements PipesInterface
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
@@ -110,7 +108,7 @@ abstract class AbstractPipes implements PipesInterface
110
  }
111
  }
112
 
113
- foreach ($r as $input) {
114
  for (;;) {
115
  $data = fread($input, self::CHUNK_SIZE);
116
  if (!isset($data[0])) {
@@ -124,7 +122,7 @@ abstract class AbstractPipes implements PipesInterface
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;
22
  public $pipes = array();
23
 
24
  /** @var string */
25
+ private $inputBuffer = '';
26
  /** @var resource|null */
27
+ private $input;
 
28
  /** @var bool */
29
  private $blocked = true;
30
 
90
  if (!isset($this->pipes[0])) {
91
  return;
92
  }
93
+ $input = $this->input;
94
+ $r = $e = array();
 
95
  $w = array($this->pipes[0]);
96
 
97
  // let's have a look if something changed in streams
108
  }
109
  }
110
 
111
+ if ($input) {
112
  for (;;) {
113
  $data = fread($input, self::CHUNK_SIZE);
114
  if (!isset($data[0])) {
122
  return array($this->pipes[0]);
123
  }
124
  }
125
+ if (feof($input)) {
126
  // no more data to read on input resource
127
  // use an empty buffer in the next reads
128
  $this->input = null;
vendor/symfony/process/Pipes/PipesInterface.php CHANGED
@@ -39,10 +39,10 @@ interface PipesInterface
39
  /**
40
  * Reads data in file handles and pipes.
41
  *
42
- * @param bool $blocking Whether to use blocking calls or not.
43
- * @param bool $close Whether to close pipes if they've reached EOF.
44
  *
45
- * @return string[] An array of read data indexed by their fd.
46
  */
47
  public function readAndWrite($blocking, $close = false);
48
 
39
  /**
40
  * Reads data in file handles and pipes.
41
  *
42
+ * @param bool $blocking Whether to use blocking calls or not
43
+ * @param bool $close Whether to close pipes if they've reached EOF
44
  *
45
+ * @return string[] An array of read data indexed by their fd
46
  */
47
  public function readAndWrite($blocking, $close = false);
48
 
vendor/symfony/process/Pipes/UnixPipes.php CHANGED
File without changes
vendor/symfony/process/Pipes/WindowsPipes.php CHANGED
@@ -47,15 +47,35 @@ class WindowsPipes extends AbstractPipes
47
  // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
48
  //
49
  // @see https://bugs.php.net/bug.php?id=51800
50
- $this->files = array(
51
- Process::STDOUT => tempnam(sys_get_temp_dir(), 'out_sf_proc'),
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);
47
  // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
48
  //
49
  // @see https://bugs.php.net/bug.php?id=51800
50
+ $pipes = array(
51
+ Process::STDOUT => Process::OUT,
52
+ Process::STDERR => Process::ERR,
53
  );
54
+ $tmpDir = sys_get_temp_dir();
55
+ $error = 'unknown reason';
56
+ set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
57
+ for ($i = 0;; ++$i) {
58
+ foreach ($pipes as $pipe => $name) {
59
+ $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
60
+ if (file_exists($file) && !unlink($file)) {
61
+ continue 2;
62
+ }
63
+ $h = fopen($file, 'xb');
64
+ if (!$h && false === strpos($error, 'File exists')) {
65
+ restore_error_handler();
66
+ throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
67
+ }
68
+ if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
69
+ continue 2;
70
+ }
71
+ if (isset($this->files[$pipe])) {
72
+ unlink($this->files[$pipe]);
73
+ }
74
+ $this->files[$pipe] = $file;
75
  }
76
+ break;
77
  }
78
+ restore_error_handler();
79
  }
80
 
81
  parent::__construct($input);
vendor/symfony/process/Process.php CHANGED
@@ -158,7 +158,7 @@ class Process
158
  $this->setEnv($env);
159
  }
160
 
161
- $this->input = $input;
162
  $this->setTimeout($timeout);
163
  $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR;
164
  $this->pty = false;
@@ -477,10 +477,10 @@ class Process
477
  * In comparison with the getOutput method which always return the whole
478
  * output, this one returns the new output since the last call.
479
  *
 
 
480
  * @throws LogicException in case the output has been disabled
481
  * @throws LogicException In case the process is not started
482
- *
483
- * @return string The process output since the last call
484
  */
485
  public function getIncrementalOutput()
486
  {
@@ -536,10 +536,10 @@ class Process
536
  * whole error output, this one returns the new error output since the last
537
  * call.
538
  *
 
 
539
  * @throws LogicException in case the output has been disabled
540
  * @throws LogicException In case the process is not started
541
- *
542
- * @return string The process error output since the last call
543
  */
544
  public function getIncrementalErrorOutput()
545
  {
@@ -593,7 +593,7 @@ class Process
593
  * This method relies on the Unix exit code status standardization
594
  * and might not be relevant for other operating systems.
595
  *
596
- * @return null|string A string representation for the exit status code, null if the Process is not terminated.
597
  *
598
  * @see http://tldp.org/LDP/abs/html/exitcodes.html
599
  * @see http://en.wikipedia.org/wiki/Unix_signal
@@ -881,7 +881,7 @@ class Process
881
  *
882
  * @param int|float|null $timeout The timeout in seconds
883
  *
884
- * @return self The current Process instance.
885
  *
886
  * @throws LogicException if the output is disabled
887
  * @throws InvalidArgumentException if the timeout is negative
@@ -1087,7 +1087,7 @@ class Process
1087
  throw new LogicException('Input can not be set while the process is running.');
1088
  }
1089
 
1090
- $this->input = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $input);
1091
 
1092
  return $this;
1093
  }
@@ -1265,7 +1265,7 @@ class Process
1265
  /**
1266
  * Updates the status of the process, reads pipes.
1267
  *
1268
- * @param bool $blocking Whether to use a blocking read call.
1269
  */
1270
  protected function updateStatus($blocking)
1271
  {
@@ -1351,8 +1351,8 @@ class Process
1351
  /**
1352
  * Reads pipes, executes callback.
1353
  *
1354
- * @param bool $blocking Whether to use blocking calls or not.
1355
- * @param bool $close Whether to close file handles or not.
1356
  */
1357
  private function readPipes($blocking, $close)
1358
  {
@@ -1478,7 +1478,7 @@ class Process
1478
  /**
1479
  * Ensures the process is running or terminated, throws a LogicException if the process has a not started.
1480
  *
1481
- * @param string $functionName The function name that was called.
1482
  *
1483
  * @throws LogicException If the process has not run.
1484
  */
@@ -1492,7 +1492,7 @@ class Process
1492
  /**
1493
  * Ensures the process is terminated, throws a LogicException if the process has a status different than `terminated`.
1494
  *
1495
- * @param string $functionName The function name that was called.
1496
  *
1497
  * @throws LogicException If the process is not yet terminated.
1498
  */
158
  $this->setEnv($env);
159
  }
160
 
161
+ $this->setInput($input);
162
  $this->setTimeout($timeout);
163
  $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR;
164
  $this->pty = false;
477
  * In comparison with the getOutput method which always return the whole
478
  * output, this one returns the new output since the last call.
479
  *
480
+ * @return string The process output since the last call
481
+ *
482
  * @throws LogicException in case the output has been disabled
483
  * @throws LogicException In case the process is not started
 
 
484
  */
485
  public function getIncrementalOutput()
486
  {
536
  * whole error output, this one returns the new error output since the last
537
  * call.
538
  *
539
+ * @return string The process error output since the last call
540
+ *
541
  * @throws LogicException in case the output has been disabled
542
  * @throws LogicException In case the process is not started
 
 
543
  */
544
  public function getIncrementalErrorOutput()
545
  {
593
  * This method relies on the Unix exit code status standardization
594
  * and might not be relevant for other operating systems.
595
  *
596
+ * @return null|string A string representation for the exit status code, null if the Process is not terminated
597
  *
598
  * @see http://tldp.org/LDP/abs/html/exitcodes.html
599
  * @see http://en.wikipedia.org/wiki/Unix_signal
881
  *
882
  * @param int|float|null $timeout The timeout in seconds
883
  *
884
+ * @return self The current Process instance
885
  *
886
  * @throws LogicException if the output is disabled
887
  * @throws InvalidArgumentException if the timeout is negative
1087
  throw new LogicException('Input can not be set while the process is running.');
1088
  }
1089
 
1090
+ $this->input = ProcessUtils::validateInput(__METHOD__, $input);
1091
 
1092
  return $this;
1093
  }
1265
  /**
1266
  * Updates the status of the process, reads pipes.
1267
  *
1268
+ * @param bool $blocking Whether to use a blocking read call
1269
  */
1270
  protected function updateStatus($blocking)
1271
  {
1351
  /**
1352
  * Reads pipes, executes callback.
1353
  *
1354
+ * @param bool $blocking Whether to use blocking calls or not
1355
+ * @param bool $close Whether to close file handles or not
1356
  */
1357
  private function readPipes($blocking, $close)
1358
  {
1478
  /**
1479
  * Ensures the process is running or terminated, throws a LogicException if the process has a not started.
1480
  *
1481
+ * @param string $functionName The function name that was called
1482
  *
1483
  * @throws LogicException If the process has not run.
1484
  */
1492
  /**
1493
  * Ensures the process is terminated, throws a LogicException if the process has a status different than `terminated`.
1494
  *
1495
+ * @param string $functionName The function name that was called
1496
  *
1497
  * @throws LogicException If the process is not yet terminated.
1498
  */
vendor/symfony/process/ProcessBuilder.php CHANGED
@@ -177,7 +177,7 @@ class ProcessBuilder
177
  */
178
  public function setInput($input)
179
  {
180
- $this->input = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $input);
181
 
182
  return $this;
183
  }
177
  */
178
  public function setInput($input)
179
  {
180
+ $this->input = ProcessUtils::validateInput(__METHOD__, $input);
181
 
182
  return $this;
183
  }
vendor/symfony/process/ProcessUtils.php CHANGED
@@ -80,7 +80,7 @@ class ProcessUtils
80
  * @param string $caller The name of method call that validates the input
81
  * @param mixed $input The input to validate
82
  *
83
- * @return string The validated input
84
  *
85
  * @throws InvalidArgumentException In case the input is not valid
86
  *
@@ -92,6 +92,9 @@ class ProcessUtils
92
  if (is_resource($input)) {
93
  return $input;
94
  }
 
 
 
95
  if (is_scalar($input)) {
96
  return (string) $input;
97
  }
80
  * @param string $caller The name of method call that validates the input
81
  * @param mixed $input The input to validate
82
  *
83
+ * @return mixed The validated input
84
  *
85
  * @throws InvalidArgumentException In case the input is not valid
86
  *
92
  if (is_resource($input)) {
93
  return $input;
94
  }
95
+ if (is_string($input)) {
96
+ return $input;
97
+ }
98
  if (is_scalar($input)) {
99
  return (string) $input;
100
  }
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
@@ -54,6 +54,9 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
54
 
55
  public function testThatProcessDoesNotThrowWarningDuringRun()
56
  {
 
 
 
57
  @trigger_error('Test Error', E_USER_NOTICE);
58
  $process = $this->getProcess(self::$phpBin." -r 'sleep(3)'");
59
  $process->run();
@@ -209,6 +212,24 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
209
  $this->assertEquals($expectedLength, strlen($p->getErrorOutput()));
210
  }
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  /**
213
  * @expectedException \Symfony\Component\Process\Exception\LogicException
214
  * @expectedExceptionMessage Input can not be set while the process is running.
@@ -1162,8 +1183,9 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
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;
@@ -1177,31 +1199,14 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
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
- */
1190
- public function methodProvider()
1191
- {
1192
- $defaults = array(
1193
- array('CommandLine'),
1194
- array('Timeout'),
1195
- array('WorkingDirectory'),
1196
- array('Env'),
1197
- array('Stdin'),
1198
- array('Input'),
1199
- array('Options'),
1200
- );
1201
-
1202
- return $defaults;
1203
- }
1204
-
1205
  /**
1206
  * @param string $commandline
1207
  * @param null|string $cwd
@@ -1224,7 +1229,7 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
1224
  } catch (RuntimeException $e) {
1225
  $this->assertSame('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.', $e->getMessage());
1226
  if ($enhance) {
1227
- $process->setEnhanceSigChildCompatibility(true);
1228
  } else {
1229
  self::$notEnhancedSigchild = true;
1230
  }
54
 
55
  public function testThatProcessDoesNotThrowWarningDuringRun()
56
  {
57
+ if ('\\' === DIRECTORY_SEPARATOR) {
58
+ $this->markTestSkipped('This test is transient on Windows');
59
+ }
60
  @trigger_error('Test Error', E_USER_NOTICE);
61
  $process = $this->getProcess(self::$phpBin." -r 'sleep(3)'");
62
  $process->run();
212
  $this->assertEquals($expectedLength, strlen($p->getErrorOutput()));
213
  }
214
 
215
+ public function testLiveStreamAsInput()
216
+ {
217
+ $stream = fopen('php://memory', 'r+');
218
+ fwrite($stream, 'hello');
219
+ rewind($stream);
220
+
221
+ $p = $this->getProcess(sprintf('%s -r %s', self::$phpBin, escapeshellarg('stream_copy_to_stream(STDIN, STDOUT);')));
222
+ $p->setInput($stream);
223
+ $p->start(function ($type, $data) use ($stream) {
224
+ if ('hello' === $data) {
225
+ fclose($stream);
226
+ }
227
+ });
228
+ $p->wait();
229
+
230
+ $this->assertSame('hello', $p->getOutput());
231
+ }
232
+
233
  /**
234
  * @expectedException \Symfony\Component\Process\Exception\LogicException
235
  * @expectedExceptionMessage Input can not be set while the process is running.
1183
  /**
1184
  * @dataProvider provideVariousIncrementals
1185
  */
1186
+ public function testIncrementalOutputDoesNotRequireAnotherCall($stream, $method)
1187
+ {
1188
+ $process = $this->getProcess(self::$phpBin.' -r '.escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\''.$stream.'\', $n, 1); $n++; usleep(1000); }'), null, null, null, null);
1189
  $process->start();
1190
  $result = '';
1191
  $limit = microtime(true) + 3;
1199
  $process->stop();
1200
  }
1201
 
1202
+ public function provideVariousIncrementals()
1203
+ {
1204
  return array(
1205
  array('php://stdout', 'getIncrementalOutput'),
1206
  array('php://stderr', 'getIncrementalErrorOutput'),
1207
  );
1208
  }
1209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1210
  /**
1211
  * @param string $commandline
1212
  * @param null|string $cwd
1229
  } catch (RuntimeException $e) {
1230
  $this->assertSame('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.', $e->getMessage());
1231
  if ($enhance) {
1232
+ $process->setEnhanceSigchildCompatibility(true);
1233
  } else {
1234
  self::$notEnhancedSigchild = true;
1235
  }
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
whitelist-html/whitelist-html.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Escapes text for HTML output, allowing certain tags
5
+ *
6
+ * Takes an arbitrary string and ensures it's safe for output into HTML. Unlike
7
+ * `esc_html`, this allows a certain subset of tags, allowing it to be used for
8
+ * strings which need to have some HTML in them (such as translated text).
9
+ *
10
+ * Allowed tags can be passed in one of two formats. The verbose form is the
11
+ * traditional kses form of
12
+ * `[ 'element' => array( 'attr' => true, 'otherattr' => true ) ]` which
13
+ * specifies tags and their attributes.
14
+ *
15
+ * The concise form, useful for inline usage on output, is in the form of
16
+ * `[ 'element', 'otherelement' ]` - This concise form takes the attribute list
17
+ * from WP core's attribute whitelist for a good-enough list for most usages.
18
+ * This can also be passed as a comma separated string.
19
+ *
20
+ * (You can also mix these forms, so something like
21
+ * `[ 'a', 'code', 'x-panel' => array( 'src' => true ) ] )` is perfectly valid.)
22
+ *
23
+ * For example:
24
+ *
25
+ * whitelist_html( __( 'Hello <a href="http://example.com">World!</a>' ), 'a' );
26
+ *
27
+ * This example would strip any tag except `a`, but would allow the default
28
+ * attributes on it (`href` and `title`).
29
+ *
30
+ * The default attributes and tags are based on {@see wp_kses_allowed_html} with
31
+ * the blank (default) "context". These are the tags in {@see $allowedtags}. To
32
+ * get all allowed post tags, pass `'post'` as the `$context` parameter, or pass
33
+ * the tags you need in the `$allowedtags` array. If a specified tag is not in
34
+ * the list, no attributes will be allowed.
35
+ *
36
+ * @link https://www.tollmanz.com/wp-kses-performance/
37
+ *
38
+ * @param string $text Content to escape
39
+ * @param array $allowedtags Allowed tags, see description.
40
+ * @param string $context kses context to use, {@see wp_kses_allowed_html}.
41
+ * @return string Escaped string for output into HTML context.
42
+ */
43
+ function whitelist_html( $text, $allowedtags = array(), $context = '' ) {
44
+ $actually_allowed = array();
45
+ $default_list = wp_kses_allowed_html( $context );
46
+
47
+ // Split comma-separated string
48
+ if ( is_string( $allowedtags ) ) {
49
+ $allowedtags = array_map( 'trim', explode( ',', $allowedtags ) );
50
+ }
51
+
52
+ foreach ( $allowedtags as $key => $tag ) {
53
+ if ( is_array( $tag ) && is_string( $key ) ) {
54
+ // kses-formatted of `'element' => [ 'attr' => true ]
55
+ // `$tag` is actually the attrs, and `$key` is the tag name
56
+ $actually_allowed[ $key ] = $tag;
57
+ continue;
58
+ }
59
+
60
+ if ( ! is_string( $tag ) ) {
61
+ // Not concise form, what even is this?
62
+ _doing_it_wrong( 'whitelist_html', '$allowedtags must consist of strings or kses-style arrays' );
63
+ continue;
64
+ }
65
+
66
+ // Grab default attributes for the tag
67
+ $attrs = array();
68
+ if ( isset( $default_list[ $tag ] ) ) {
69
+ $attrs = $default_list[ $tag ];
70
+ }
71
+
72
+ // Add to allowed list
73
+ $actually_allowed[ $tag ] = $attrs;
74
+ }
75
+
76
+ // Do the sanitization dance
77
+ $sanitized = wp_kses( $text, $actually_allowed );
78
+
79
+ /**
80
+ * Filter a string to be output into HTML, allowing some tags
81
+ *
82
+ * @param string $sanitized The text after it has been escaped.
83
+ * @param string $text The text before it has been escaped.
84
+ * @param string $allowedtags Tags requested to whitelist.
85
+ * @param string
86
+ */
87
+ return apply_filters( 'whitelist_html', $sanitized, $text, $allowedtags, $context );
88
+ }
89
+
90
+ /**
91
+ * Escapes text for HTML output, allowing certain tags, then outputs.
92
+ *
93
+ * @see whitelist_html
94
+ *
95
+ * @param string $text Content to escape
96
+ * @param array $allowedtags Allowed tags, {@see whitelist_html}.
97
+ * @param string $context kses context to use, {@see wp_kses_allowed_html}.
98
+ * @return string Escaped string for output into HTML context.
99
+ */
100
+ function print_whitelist_html( $text, $allowedtags = array(), $context = '' ) {
101
+ echo whitelist_html( $text, $allowedtags, $context );
102
+ }