Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"post-install-cmd": [
"@php patches/fix-runner-set-alias.php"
],
"post-update-cmd": [
"@php patches/fix-runner-set-alias.php"
],
"behat": "run-behat-tests",
"behat-rerun": "rerun-behat-tests",
"lint": "run-linter-tests",
Expand Down
23 changes: 23 additions & 0 deletions features/search-replace.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1637,3 +1637,26 @@ Feature: Do global search/replace
"""
Table is read-only
"""

@require-mysql
Scenario: Global runtime parameters are accepted when used alongside an alias
Given a WP install
And a wp-cli.yml file:
"""
'@local':
url: https://example.com
"""

When I run `wp @local --url=https://example.com search-replace foo bar`
Then STDOUT should contain:
"""
Success:
"""
And STDERR should be empty

When I run `wp @local --url=https://example.com search-replace foo bar --dry-run`
Then STDOUT should contain:
"""
Success:
"""
And STDERR should be empty
86 changes: 86 additions & 0 deletions patches/fix-runner-set-alias.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

/**
* Patches a bug in WP_CLI\Runner::set_alias() where global runtime parameters
* (url, path, user, etc.) could be injected into $this->assoc_args when both
* an alias and a matching CLI flag were present simultaneously, causing the
* subcommand dispatcher to reject them as "unknown" parameters.
*
* This patch can be removed once wp-cli/wp-cli ships the fix upstream.
*
* @see https://github.com/wp-cli/search-replace-command/issues/225
*/

$file = __DIR__ . '/../vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php';

if ( ! file_exists( $file ) ) {
return;
}

$contents = file_get_contents( $file );

// Marker that indicates the fix has already been applied.
if ( false !== strpos( $contents, 'fix-runner-set-alias-applied' ) ) {
return;
}

$old = <<<'PHP'
private function set_alias( $alias ): void {
$orig_config = $this->config;
/** @var array<string, mixed> $alias_config */
// @phpstan-ignore varTag.type
$alias_config = (array) $this->aliases[ $alias ];
$this->config = array_merge( $orig_config, $alias_config );
foreach ( $alias_config as $key => $_ ) {
if ( isset( $orig_config[ (string) $key ] ) && ! is_null( $orig_config[ (string) $key ] ) ) {
// @phpstan-ignore assign.propertyType
$this->assoc_args[ (string) $key ] = $orig_config[ (string) $key ];
}
}
}
PHP;

$new = <<<'PHP'
private function set_alias( $alias ): void {
// fix-runner-set-alias-applied
$orig_config = $this->config;
/** @var array<string, mixed> $alias_config */
// @phpstan-ignore varTag.type
$alias_config = (array) $this->aliases[ $alias ];
$this->config = array_merge( $orig_config, $alias_config );
// Global runtime parameters (url, path, user, etc.) are managed
// entirely through the config system. Putting them into $assoc_args
// causes subcommand validation to reject them as "unknown" parameters.
static $runtime_keys = null;
if ( null === $runtime_keys ) {
$runtime_keys = array_keys(
array_filter(
WP_CLI::get_configurator()->get_spec(),
static function ( $details ) {
return false !== $details['runtime'];
}
)
);
}
foreach ( $alias_config as $key => $_ ) {
if ( in_array( $key, $runtime_keys, true ) ) {
continue;
}
if ( isset( $orig_config[ (string) $key ] ) && ! is_null( $orig_config[ (string) $key ] ) ) {
// @phpstan-ignore assign.propertyType
$this->assoc_args[ (string) $key ] = $orig_config[ (string) $key ];
}
}
}
PHP;

if ( false === strpos( $contents, $old ) ) {
// The original code was not found – the upstream may have already fixed
// this or the file structure changed. Either way, do nothing.
fwrite( STDERR, "Notice: patches/fix-runner-set-alias.php — could not locate the target code in {$file}. " .
"The patch was not applied. This is expected if the upstream fix has already been merged into wp-cli/wp-cli.\n" );
return;
}

$patched = str_replace( $old, $new, $contents );
file_put_contents( $file, $patched );
3 changes: 3 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
<!-- What to scan. -->
<file>.</file>

<!-- Exclude the patches directory – it contains build utilities, not plugin/theme code. -->
<exclude-pattern>*/patches/*</exclude-pattern>

<!-- Show progress. -->
<arg value="p"/>

Expand Down