Ticket #6531: 6531.11.diff
File 6531.11.diff, 11.0 KB (added by , 7 years ago) |
---|
-
src/wp-admin/includes/file.php
diff --git src/wp-admin/includes/file.php src/wp-admin/includes/file.php index 553880a46c..c93dc9e0d7 100644
function get_home_path() { 123 123 * 124 124 * @param string $folder Optional. Full path to folder. Default empty. 125 125 * @param int $levels Optional. Levels of folders to follow, Default 100 (PHP Loop limit). 126 * @param array $exclusions Optional. List of folders to skip. 126 127 * @return bool|array False on failure, Else array of files 127 128 */ 128 function list_files( $folder = '', $levels = 100 ) {129 if ( empty( $folder) )129 function list_files( $folder = '', $levels = 100, $exclusions = array() ) { 130 if ( empty( $folder ) ) { 130 131 return false; 132 } 133 134 $folder = trailingslashit( $folder ); 131 135 132 if ( ! $levels ) 136 if ( ! $levels ) { 133 137 return false; 138 } 134 139 135 140 $files = array(); 136 if ( $dir = @opendir( $folder ) ) { 137 while (($file = readdir( $dir ) ) !== false ) { 138 if ( in_array($file, array('.', '..') ) ) 141 142 $dir = @opendir( $folder ); 143 if ( $dir ) { 144 while ( ( $file = readdir( $dir ) ) !== false ) { 145 // Skip current and parent folder links. 146 if ( in_array( $file, array( '.', '..' ), true ) ) { 147 continue; 148 } 149 150 // Skip hidden and excluded files. 151 if ( '.' === $file[0] || in_array( $file, $exclusions, true ) ) { 139 152 continue; 140 if ( is_dir( $folder . '/' . $file ) ) { 141 $files2 = list_files( $folder . '/' . $file, $levels - 1); 142 if ( $files2 ) 153 } 154 155 if ( is_dir( $folder . $file ) ) { 156 $files2 = list_files( $folder . $file, $levels - 1 ); 157 if ( $files2 ) { 143 158 $files = array_merge($files, $files2 ); 144 else 145 $files[] = $folder . '/' . $file . '/'; 159 } else { 160 $files[] = $folder . $file . '/'; 161 } 146 162 } else { 147 $files[] = $folder . '/' .$file;163 $files[] = $folder . $file; 148 164 } 149 165 } 150 166 } 151 167 @closedir( $dir ); 168 152 169 return $files; 153 170 } 154 171 -
src/wp-admin/includes/plugin.php
diff --git src/wp-admin/includes/plugin.php src/wp-admin/includes/plugin.php index 69aeacda2f..272b333a68 100644
function _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup 190 190 * @param string $plugin Path to the main plugin file from plugins directory. 191 191 * @return array List of files relative to the plugin root. 192 192 */ 193 function get_plugin_files( $plugin) {193 function get_plugin_files( $plugin ) { 194 194 $plugin_file = WP_PLUGIN_DIR . '/' . $plugin; 195 $dir = dirname($plugin_file); 196 $plugin_files = array($plugin); 197 if ( is_dir($dir) && $dir != WP_PLUGIN_DIR ) { 198 $plugins_dir = @ opendir( $dir ); 199 if ( $plugins_dir ) { 200 while (($file = readdir( $plugins_dir ) ) !== false ) { 201 if ( substr($file, 0, 1) == '.' ) 202 continue; 203 if ( is_dir( $dir . '/' . $file ) ) { 204 $plugins_subdir = @ opendir( $dir . '/' . $file ); 205 if ( $plugins_subdir ) { 206 while (($subfile = readdir( $plugins_subdir ) ) !== false ) { 207 if ( substr($subfile, 0, 1) == '.' ) 208 continue; 209 $plugin_files[] = plugin_basename("$dir/$file/$subfile"); 210 } 211 @closedir( $plugins_subdir ); 212 } 213 } else { 214 if ( plugin_basename("$dir/$file") != $plugin ) 215 $plugin_files[] = plugin_basename("$dir/$file"); 216 } 217 } 218 @closedir( $plugins_dir ); 219 } 195 $dir = dirname( $plugin_file ); 196 197 $data = get_plugin_data( $plugin_file ); 198 $label = isset( $data['Version'] ) 199 ? sanitize_key( 'files_' . $plugin . '-' . $data['Version'] ) 200 : sanitize_key( 'files_' . $plugin ); 201 $transient_key = substr( $label, 0, 29 ) . md5( $label ); 202 203 $plugin_files = false; //get_transient( $transient_key ); 204 if ( false !== $plugin_files ) { 205 return $plugin_files; 220 206 } 221 207 208 $plugin_files = array( plugin_basename( $plugin_file ) ); 209 210 if ( is_dir( $dir ) && WP_PLUGIN_DIR !== $dir ) { 211 212 /** 213 * Filters the array of excluded directories and files while scanning the folder. 214 * 215 * @since 4.9 216 * 217 * @param array $exclusions Array of excluded directories and files. 218 */ 219 $exclusions = (array) apply_filters( 'get_plugin_files_exclusions', array( 'CVS', 'node_modules', 'vendor', 'bower_components' ) ); 220 221 $list_files = list_files( $dir, 100, $exclusions ); 222 $list_files = array_map( 'plugin_basename', $list_files ); 223 224 $plugin_files += $list_files; 225 $plugin_files = array_unique( $plugin_files ); 226 } 227 228 set_transient( $transient_key, $plugin_files, HOUR_IN_SECONDS ); 229 222 230 return $plugin_files; 223 231 } 224 232 -
src/wp-admin/theme-editor.php
diff --git src/wp-admin/theme-editor.php src/wp-admin/theme-editor.php index ebac61b538..70629d914d 100644
$file_types = wp_get_theme_file_editable_extensions( $theme ); 75 75 foreach ( $file_types as $type ) { 76 76 switch ( $type ) { 77 77 case 'php': 78 $allowed_files += $theme->get_files( 'php', 1 );78 $allowed_files += $theme->get_files( 'php', -1 ); 79 79 $has_templates = ! empty( $allowed_files ); 80 80 break; 81 81 case 'css': 82 $style_files = $theme->get_files( 'css' );82 $style_files = $theme->get_files( 'css', -1 ); 83 83 $allowed_files['style.css'] = $style_files['style.css']; 84 84 $allowed_files += $style_files; 85 85 break; 86 86 default: 87 $allowed_files += $theme->get_files( $type );87 $allowed_files += $theme->get_files( $type, -1 ); 88 88 break; 89 89 } 90 90 } -
src/wp-includes/class-wp-theme.php
diff --git src/wp-includes/class-wp-theme.php src/wp-includes/class-wp-theme.php index 30e9226132..4dd0a75016 100644
final class WP_Theme implements ArrayAccess { 981 981 * @param int $depth Optional. How deep to search for files. Defaults to a flat scan (0 depth). -1 depth is infinite. 982 982 * @param bool $search_parent Optional. Whether to return parent files. Defaults to false. 983 983 * @return array Array of files, keyed by the path to the file relative to the theme's directory, with the values 984 * 984 * being absolute paths. 985 985 */ 986 986 public function get_files( $type = null, $depth = 0, $search_parent = false ) { 987 $files = (array) self::scandir( $this->get_stylesheet_directory(), $type, $depth ); 987 // get and cache all theme files to start with. 988 $label = sanitize_key( 'files_' . $this->cache_hash . '-' . $this->get( 'Version' ) ); 989 $transient_key = substr( $label, 0, 29 ) . md5( $label ); 988 990 989 if ( $search_parent && $this->parent() ) 990 $files += (array) self::scandir( $this->get_template_directory(), $type, $depth ); 991 $all_files = get_transient( $transient_key ); 992 if ( false === $all_files ) { 993 $all_files = (array) self::scandir( $this->get_stylesheet_directory(), null, -1 ); 994 995 if ( $search_parent && $this->parent() ) { 996 $all_files += (array) self::scandir( $this->get_template_directory(), null, -1 ); 997 } 998 999 set_transient( $transient_key, $all_files, HOUR_IN_SECONDS ); 1000 } 1001 1002 // Filter $all_files by $type & $depth. 1003 $files = array(); 1004 if ( $type ) { 1005 $type = (array) $type; 1006 $_extensions = implode( '|', $type ); 1007 } 1008 foreach ( $all_files as $key => $file ) { 1009 if ( $depth >= 0 && substr_count( $key, '/' ) > $depth ) { 1010 continue; // Filter by depth. 1011 } 1012 if ( ! $type || preg_match( '~\.(' . $_extensions . ')$~', $file ) ) { // Filter by type. 1013 $files[ $key ] = $file; 1014 } 1015 } 991 1016 992 1017 return $files; 993 1018 } … … final class WP_Theme implements ArrayAccess { 1107 1132 * with `$relative_path`, with the values being absolute paths. False otherwise. 1108 1133 */ 1109 1134 private static function scandir( $path, $extensions = null, $depth = 0, $relative_path = '' ) { 1110 if ( ! is_dir( $path ) ) 1135 if ( ! is_dir( $path ) ) { 1111 1136 return false; 1137 } 1112 1138 1113 1139 if ( $extensions ) { 1114 1140 $extensions = (array) $extensions; … … final class WP_Theme implements ArrayAccess { 1116 1142 } 1117 1143 1118 1144 $relative_path = trailingslashit( $relative_path ); 1119 if ( '/' == $relative_path ) 1145 if ( '/' == $relative_path ) { 1120 1146 $relative_path = ''; 1147 } 1121 1148 1122 1149 $results = scandir( $path ); 1123 1150 $files = array(); … … final class WP_Theme implements ArrayAccess { 1125 1152 /** 1126 1153 * Filters the array of excluded directories and files while scanning theme folder. 1127 1154 * 1128 1155 * @since 4.7.4 1129 1156 * 1130 1157 * @param array $exclusions Array of excluded directories and files. 1131 1158 */ 1132 $exclusions = (array) apply_filters( 'theme_scandir_exclusions', array( 'CVS', 'node_modules' ) );1159 $exclusions = (array) apply_filters( 'theme_scandir_exclusions', array( 'CVS', 'node_modules', 'vendor', 'bower_components' ) ); 1133 1160 1134 1161 foreach ( $results as $result ) { 1135 1162 if ( '.' == $result[0] || in_array( $result, $exclusions, true ) ) { 1136 1163 continue; 1137 1164 } 1138 1165 if ( is_dir( $path . '/' . $result ) ) { 1139 if ( ! $depth ) 1166 if ( ! $depth ) { 1140 1167 continue; 1168 } 1141 1169 $found = self::scandir( $path . '/' . $result, $extensions, $depth - 1 , $relative_path . $result ); 1142 1170 $files = array_merge_recursive( $files, $found ); 1143 1171 } elseif ( ! $extensions || preg_match( '~\.(' . $_extensions . ')$~', $result ) ) { -
tests/phpunit/tests/admin/includesPlugin.php
diff --git tests/phpunit/tests/admin/includesPlugin.php tests/phpunit/tests/admin/includesPlugin.php index b7ed20dd90..29bc84dfe5 100644
class Tests_Admin_includesPlugin extends WP_UnitTestCase { 93 93 $this->assertEquals( array( $name ), get_plugin_files( $name ) ); 94 94 } 95 95 96 /** 97 * @covers ::get_plugin_files 98 */ 99 public function test_get_plugin_files_folder() { 100 $plugin_dir = WP_PLUGIN_DIR . '/list_files_test_plugin'; 101 @mkdir( $plugin_dir ); 102 $plugin = $this->_create_plugin(null, 'list_files_test_plugin.php', $plugin_dir ); 103 104 $sub_dir = trailingslashit( dirname( $plugin[1] ) ) . 'subdir'; 105 @mkdir( $sub_dir ); 106 @file_put_contents( $sub_dir . '/subfile.php', '<?php // Silence.' ); 107 108 $plugin_files = get_plugin_files( plugin_basename( $plugin[1] ) ); 109 $expected = array( 110 'list_files_test_plugin/list_files_test_plugin.php', 111 'list_files_test_plugin/subdir/subfile.php', 112 ); 113 $this->assertEquals( $expected, $plugin_files ); 114 115 unlink( $sub_dir . '/subfile.php' ); 116 unlink( $plugin[1] ); 117 rmdir( $sub_dir ); 118 rmdir( $plugin_dir ); 119 } 120 96 121 /** 97 122 * @covers ::get_mu_plugins 98 123 */ -
new file tests/phpunit/tests/functions/listFiles.php
diff --git tests/phpunit/tests/functions/listFiles.php tests/phpunit/tests/functions/listFiles.php new file mode 100644 index 0000000000..c464382fe2
- + 1 <?php 2 3 /** 4 * Test list_files(). 5 * 6 * @group functions.php 7 */ 8 class Tests_Functions_ListFiles extends WP_UnitTestCase { 9 10 public function test_list_files_returns_a_list_of_files() { 11 $admin_files = list_files( ABSPATH . 'wp-admin/' ); 12 $this->assertInternalType( 'array', $admin_files ); 13 $this->assertNotEmpty( $admin_files ); 14 $this->assertTrue( in_array( ABSPATH . 'wp-admin/about.php', $admin_files, true ) ); 15 } 16 17 public function test_list_files_can_exclude_files() { 18 $admin_files = list_files( ABSPATH . 'wp-admin/', 100, array( 'about.php' ) ); 19 $this->assertFalse( in_array( ABSPATH . 'wp-admin/about.php', $admin_files, true ) ); 20 } 21 }