diff --git a/files/class-vip-filesystem-local-stream-wrapper.php b/files/class-vip-filesystem-local-stream-wrapper.php index cca388310a..c0fb026a61 100644 --- a/files/class-vip-filesystem-local-stream-wrapper.php +++ b/files/class-vip-filesystem-local-stream-wrapper.php @@ -129,6 +129,13 @@ class VIP_Filesystem_Local_Stream_Wrapper { */ private static $local_file_patterns = array(); + /** + * HashMap of filename substrings for local files + * + * @var array + */ + private static $local_file_names = array(); + /** * File handle for local files * @@ -1152,6 +1159,8 @@ public static function add_local_file( $file_path ) { if ( $is_pattern ) { static::$local_file_patterns[ $file_path ] = true; + } elseif ( false === strpos( $file_path, '/' ) ) { + static::$local_file_names[ $file_path ] = true; } else { static::$local_files_map[ $file_path ] = true; } @@ -1168,16 +1177,17 @@ public static function add_local_file( $file_path ) { public static function remove_local_file( $file_path ) { unset( static::$local_file_patterns[ $file_path ] ); unset( static::$local_files_map[ $file_path ] ); + unset( static::$local_file_names[ $file_path ] ); return true; } /** * Get the list of files that should be handled locally * - * @return array List of file paths and patterns + * @return array List of file paths, patterns and file names */ public static function get_local_files() { - return array_merge( static::$local_files_map, static::$local_file_patterns ); + return array_merge( static::$local_files_map, static::$local_file_patterns, static::$local_file_names ); } /** @@ -1192,6 +1202,14 @@ public static function is_local_file( $file_path ) { return true; } + // Check if any filename substring is present in the filename. + $file_name = \wp_basename( $file_path ); + foreach ( static::$local_file_names as $name => $value ) { + if ( false !== strpos( $file_name, $name ) ) { + return true; + } + } + // Check against wildcard patterns foreach ( static::$local_file_patterns as $pattern => $value ) { if ( fnmatch( $pattern, $file_path, FNM_PATHNAME ) ) { diff --git a/tests/files/test-vip-filesystem-local-stream-wrapper.php b/tests/files/test-vip-filesystem-local-stream-wrapper.php index 3c80953e7b..dbabb0a08f 100644 --- a/tests/files/test-vip-filesystem-local-stream-wrapper.php +++ b/tests/files/test-vip-filesystem-local-stream-wrapper.php @@ -478,6 +478,18 @@ public function test_lookup_optimization() { } } + public function test_filename_substring_matching() { + $this->assertFalse( VIP_Filesystem_Local_Stream_Wrapper::is_local_file( 'vip://wp-content/uploads/.htaccess' ) ); + + VIP_Filesystem_Local_Stream_Wrapper::add_local_file( '.htaccess' ); + $this->assertTrue( VIP_Filesystem_Local_Stream_Wrapper::is_local_file( 'vip://wp-content/uploads/.htaccess' ) ); + $this->assertTrue( VIP_Filesystem_Local_Stream_Wrapper::is_local_file( 'vip://wp-content/uploads/cache/.htaccess.backup' ) ); + $this->assertFalse( VIP_Filesystem_Local_Stream_Wrapper::is_local_file( 'vip://wp-content/uploads/cache/htaccess.txt' ) ); + + VIP_Filesystem_Local_Stream_Wrapper::remove_local_file( '.htaccess' ); + $this->assertFalse( VIP_Filesystem_Local_Stream_Wrapper::is_local_file( 'vip://wp-content/uploads/.htaccess' ) ); + } + public function test__global_helpers__add() { // Add files using the global helper $result = wpvip_fs_local_file_add( 'vip://wp-content/uploads/direct.txt' );