diff --git a/composer.json b/composer.json index da4eba6..3321246 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ }, "require": { "php": ">=7.2.24", - "wp-cli/wp-cli": "^2.12" + "wp-cli/wp-cli": "^2.13" }, "require-dev": { "wp-cli/wp-cli-tests": "^5.0.0" diff --git a/features/find.feature b/features/find.feature index ae50d10..eb27edd 100644 --- a/features/find.feature +++ b/features/find.feature @@ -4,7 +4,7 @@ Feature: Find WordPress installs on the filesystem Given a WP install in 'subdir1' And a WP install in 'subdir2' - When I run `wp eval --skip-wordpress 'echo realpath( getenv( "RUN_DIR" ) );'` + When I run `wp eval --skip-wordpress "echo WP_CLI\Path::normalize( realpath( getenv( 'RUN_DIR' ) ) );"` Then save STDOUT as {TEST_DIR} When I run `wp find {TEST_DIR} --field=version_path | sort` @@ -35,7 +35,7 @@ Feature: Find WordPress installs on the filesystem And a WP install in 'cache' And a WP install in 'tmp' - When I run `wp eval --skip-wordpress 'echo realpath( getenv( "RUN_DIR" ) );'` + When I run `wp eval --skip-wordpress "echo WP_CLI\Path::normalize( realpath( getenv( 'RUN_DIR' ) ) );"` Then save STDOUT as {TEST_DIR} When I run `wp find {TEST_DIR} --field=version_path --verbose` @@ -70,11 +70,11 @@ Feature: Find WordPress installs on the filesystem Scenario: Use --max_depth= to specify max recursion depth Given a WP install in 'subdir1' - And I run `mkdir -p sub/sub` + And an empty sub/sub directory And a WP install in 'sub/subdir2' And a WP install in 'sub/sub/subdir3' - When I run `wp eval --skip-wordpress 'echo realpath( getenv( "RUN_DIR" ) );'` + When I run `wp eval --skip-wordpress "echo WP_CLI\Path::normalize( realpath( getenv( 'RUN_DIR' ) ) );"` Then save STDOUT as {TEST_DIR} When I run `wp find {TEST_DIR} --verbose` @@ -166,11 +166,14 @@ Feature: Find WordPress installs on the filesystem Given a WP install in 'subdir1' And a WP install in 'subdir2' - When I run `wp eval --skip-wordpress 'echo realpath( getenv( "RUN_DIR" ) );'` + When I run `wp eval --skip-wordpress "echo WP_CLI\Path::normalize( realpath( getenv( 'RUN_DIR' ) ) );"` Then save STDOUT as {TEST_DIR} - When I run `echo "@test1:\n path: {TEST_DIR}/subdir2" > wp-cli.yml` - Then the return code should be 0 + Given a wp-cli.yml file: + """ + @test1: + path: {TEST_DIR}/subdir2 + """ When I run `wp find {TEST_DIR} --fields=version_path,alias` Then STDOUT should be a table containing rows: @@ -181,10 +184,10 @@ Feature: Find WordPress installs on the filesystem Scenario: Ignore hidden directories by default Given a WP install in 'subdir1' And a WP install in '.svn' - And I run `mkdir -p subdir2/.svn` + And an empty subdir2/.svn directory And a WP install in 'subdir2/.svn/wp-install' - When I run `wp eval --skip-wordpress 'echo realpath( getenv( "RUN_DIR" ) );'` + When I run `wp eval --skip-wordpress "echo WP_CLI\Path::normalize( realpath( getenv( 'RUN_DIR' ) ) );"` Then save STDOUT as {TEST_DIR} When I run `wp find {TEST_DIR} --format=count` @@ -203,7 +206,7 @@ Feature: Find WordPress installs on the filesystem Given a WP install in 'subdir1' And a WP install in 'subdir2' - When I run `wp eval --skip-wordpress 'echo realpath( getenv( "RUN_DIR" ) );'` + When I run `wp eval --skip-wordpress "echo WP_CLI\Path::normalize( realpath( getenv( 'RUN_DIR' ) ) );"` Then save STDOUT as {TEST_DIR} When I run `wp find {TEST_DIR} --format=count` @@ -212,7 +215,7 @@ Feature: Find WordPress installs on the filesystem 2 """ - When I run `wp find {TEST_DIR} --include_ignored_paths='/subdir1/,/apple/' --format=count` + When I run `wp find {TEST_DIR} "--include_ignored_paths=subdir1,apple" --format=count` Then STDOUT should be: """ 1 @@ -224,7 +227,7 @@ Feature: Find WordPress installs on the filesystem And a WP install in 'logs' And a WP install in 'js' - When I run `wp eval --skip-wordpress 'echo realpath( getenv( "RUN_DIR" ) );'` + When I run `wp eval --skip-wordpress "echo WP_CLI\Path::normalize( realpath( getenv( 'RUN_DIR' ) ) );"` Then save STDOUT as {TEST_DIR} When I run `wp find {TEST_DIR} --field=version_path --verbose` diff --git a/src/Find_Command.php b/src/Find_Command.php index 02ef100..2c1b6c6 100644 --- a/src/Find_Command.php +++ b/src/Find_Command.php @@ -2,6 +2,7 @@ use WP_CLI\Utils; use WP_CLI\Formatter; +use WP_CLI\Path; class Find_Command { @@ -189,14 +190,23 @@ class Find_Command { * @when before_wp_load */ public function __invoke( $args, $assoc_args ) { - list( $path ) = $args; - $this->base_path = (string) realpath( $path ); - if ( ! $this->base_path ) { + list( $path ) = $args; + $base_path = (string) realpath( $path ); + if ( ! $base_path ) { WP_CLI::error( 'Invalid path specified.' ); } + $this->base_path = Path::normalize( $base_path ); $this->skip_ignored_paths = Utils\get_flag_value( $assoc_args, 'skip-ignored-paths' ); if ( ! empty( $assoc_args['include_ignored_paths'] ) ) { - $this->ignored_paths = array_merge( $this->ignored_paths, explode( ',', $assoc_args['include_ignored_paths'] ) ); + $included_paths = explode( ',', trim( $assoc_args['include_ignored_paths'], "\"' " ) ); + $included_paths = array_map( + static function ( $path ) { + $path = Path::normalize( trim( $path, "\"' " ) ); + return ltrim( rtrim( $path, '/' ) . '/', '/' ); + }, + $included_paths + ); + $this->ignored_paths = array_merge( $this->ignored_paths, $included_paths ); } $this->max_depth = Utils\get_flag_value( $assoc_args, 'max_depth', false ); $this->verbose = Utils\get_flag_value( $assoc_args, 'verbose' ); @@ -206,12 +216,18 @@ public function __invoke( $args, $assoc_args ) { if ( empty( $target['path'] ) ) { continue; } - $this->resolved_aliases[ rtrim( $target['path'], '/' ) ] = $alias; + $this->resolved_aliases[ rtrim( Path::normalize( $target['path'] ), '/' ) ] = $alias; } $fields = [ 'version_path', 'version', 'depth', 'alias' ]; if ( ! empty( $assoc_args['fields'] ) ) { - $fields = explode( ',', $assoc_args['fields'] ); + $fields = explode( ',', trim( $assoc_args['fields'], "\"' " ) ); + $fields = array_map( + static function ( $field ) { + return trim( $field, "\"' " ); + }, + $fields + ); } $this->start_time = microtime( true ); @@ -229,15 +245,18 @@ private function recurse_directory( $path ) { return; } + $path = Path::normalize( $path ); + // Provide consistent trailing slashes to all paths $path = rtrim( $path, '/' ) . '/'; // Don't recurse directories that probably don't have a WordPress installation. if ( ! $this->skip_ignored_paths ) { // Assume base path doesn't need comparison - $compared_path = (string) preg_replace( '#^' . preg_quote( $this->base_path, '#' ) . '#', '', $path ); + $compared_path = (string) preg_replace( '#^' . preg_quote( $this->base_path, '#' ) . '#' . ( '\\' === DIRECTORY_SEPARATOR ? 'i' : '' ), '', $path ); // Ignore all hidden system directories - $bits = explode( '/', trim( $compared_path, '/' ) ); + $bits = explode( '/', trim( $compared_path, '/' ) ); + $current_dir = array_pop( $bits ); if ( $current_dir && '.' === $current_dir[0] ) { $this->log( "Matched ignored path. Skipping recursion into '{$path}'" ); @@ -254,11 +273,11 @@ private function recurse_directory( $path ) { // This looks like a wp-includes directory, so check if it has a // version.php file. - if ( DIRECTORY_SEPARATOR . 'wp-includes/' === substr( $path, -13 ) + if ( '/wp-includes/' === substr( $path, -13 ) && file_exists( $path . 'version.php' ) ) { $version_path = $path . 'version.php'; $wp_path = substr( $path, 0, -13 ); - $alias = isset( $this->resolved_aliases[ $wp_path ] ) ? $this->resolved_aliases[ $wp_path ] : ''; + $alias = isset( $this->resolved_aliases[ $wp_path ] ) ? '@' . $this->resolved_aliases[ $wp_path ] : ''; $wp_path = rtrim( $wp_path, '/' ) . '/'; $this->found_wp[ $version_path ] = [ @@ -346,7 +365,7 @@ private static function get_wp_config_path( $installation_dir ) { } if ( $path ) { - $path = realpath( $path ); + $path = Path::normalize( (string) realpath( $path ) ); } return $path; }