Skip to content

Commit e5d16b7

Browse files
committed
solve conflicts
2 parents da44f6a + df1092f commit e5d16b7

File tree

6 files changed

+122
-13
lines changed

6 files changed

+122
-13
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ before_install:
4747
else
4848
echo "xdebug.ini does not exist"
4949
fi
50+
- |
51+
# Raise PHP memory limit to 2048MB
52+
echo 'memory_limit = 2048M' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
5053
5154
install:
5255
- composer require wp-cli/wp-cli:dev-master

bin/test.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ then
88
phpunit
99
fi
1010

11+
if [ $WP_VERSION = "latest" ]; then
12+
export WP_VERSION=$(curl -s https://api.wordpress.org/core/version-check/1.7/ | jq -r ".offers[0].current")
13+
fi
14+
1115
# Run the functional tests
1216
BEHAT_TAGS=$(php utils/behat-tags.php)
1317
behat --format progress $BEHAT_TAGS --strict

features/bootstrap/utils.php

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function extract_from_phar( $path ) {
2424

2525
$fname = basename( $path );
2626

27-
$tmp_path = get_temp_dir() . "wp-cli-$fname";
27+
$tmp_path = get_temp_dir() . uniqid( 'wp-cli-extract-from-phar-', true ) . "-$fname";
2828

2929
copy( $path, $tmp_path );
3030

@@ -351,19 +351,21 @@ function pick_fields( $item, $fields ) {
351351
* @category Input
352352
*
353353
* @param string $content Some form of text to edit (e.g. post content)
354+
* @param string $title Title to display in the editor.
355+
* @param string $ext Extension to use with the temp file.
354356
* @return string|bool Edited text, if file is saved from editor; false, if no change to file.
355357
*/
356-
function launch_editor_for_input( $input, $filename = 'WP-CLI' ) {
358+
function launch_editor_for_input( $input, $title = 'WP-CLI', $ext = 'tmp' ) {
357359

358360
check_proc_available( 'launch_editor_for_input' );
359361

360362
$tmpdir = get_temp_dir();
361363

362364
do {
363-
$tmpfile = basename( $filename );
365+
$tmpfile = basename( $title );
364366
$tmpfile = preg_replace( '|\.[^.]*$|', '', $tmpfile );
365367
$tmpfile .= '-' . substr( md5( mt_rand() ), 0, 6 );
366-
$tmpfile = $tmpdir . $tmpfile . '.tmp';
368+
$tmpfile = $tmpdir . $tmpfile . '.' . $ext;
367369
$fp = fopen( $tmpfile, 'xb' );
368370
if ( ! $fp && is_writable( $tmpdir ) && file_exists( $tmpfile ) ) {
369371
$tmpfile = '';
@@ -772,6 +774,31 @@ function trailingslashit( $string ) {
772774
return rtrim( $string, '/\\' ) . '/';
773775
}
774776

777+
/**
778+
* Normalize a filesystem path.
779+
*
780+
* On Windows systems, replaces backslashes with forward slashes
781+
* and forces upper-case drive letters.
782+
* Allows for two leading slashes for Windows network shares, but
783+
* ensures that all other duplicate slashes are reduced to a single one.
784+
* Ensures upper-case drive letters on Windows systems.
785+
*
786+
* @access public
787+
* @category System
788+
*
789+
* @param string $path Path to normalize.
790+
* @return string Normalized path.
791+
*/
792+
function normalize_path( $path ) {
793+
$path = str_replace( '\\', '/', $path );
794+
$path = preg_replace( '|(?<=.)/+|', '/', $path );
795+
if ( ':' === substr( $path, 1, 1 ) ) {
796+
$path = ucfirst( $path );
797+
}
798+
return $path;
799+
}
800+
801+
775802
/**
776803
* Convert Windows EOLs to *nix.
777804
*
@@ -1307,6 +1334,7 @@ function get_php_binary() {
13071334

13081335
// Available since PHP 5.4.
13091336
if ( defined( 'PHP_BINARY' ) ) {
1337+
// @codingStandardsIgnoreLine
13101338
return PHP_BINARY;
13111339
}
13121340

features/search-replace-export.feature

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,12 @@ Feature: Search / replace with file export
6464
When I run `wp search-replace example.com example.net --export=wordpress.sql`
6565
Then STDOUT should contain:
6666
"""
67-
Success: Made 110 replacements and exported to wordpress.sql
67+
Success: Made
68+
"""
69+
# Skip exact number as it changes in trunk due to https://core.trac.wordpress.org/changeset/42981
70+
And STDOUT should contain:
71+
"""
72+
replacements and exported to wordpress.sql
6873
"""
6974
And STDOUT should be a table containing rows:
7075
| Table | Column | Replacements | Type |

features/search-replace.feature

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ Feature: Do global search/replace
3232
And I run `wp site create --slug="foo" --title="foo" --email="foo@example.com"`
3333
And I run `wp search-replace foo bar --network`
3434
Then STDOUT should be a table containing rows:
35-
| Table | Column | Replacements | Type |
36-
| wp_2_posts | guid | 2 | SQL |
37-
| wp_blogs | path | 1 | SQL |
35+
| Table | Column | Replacements | Type |
36+
| wp_2_options | option_value | 4 | PHP |
37+
| wp_blogs | path | 1 | SQL |
3838

3939
Scenario: Don't run on unregistered tables by default
4040
Given a WP install
@@ -277,6 +277,8 @@ Feature: Do global search/replace
277277
| wp_multicol | name | 1 | SQL |
278278
| wp_multicol | value | 1 | SQL |
279279

280+
# Skip on 5.0 for now due to difficulties introduced by https://core.trac.wordpress.org/changeset/42981
281+
@less-than-wp-5.0
280282
Scenario Outline: Large guid search/replace where replacement contains search (or not)
281283
Given a WP install
282284
And I run `wp option get siteurl`
@@ -1031,6 +1033,28 @@ Feature: Do global search/replace
10311033
Success: 1 replacement to be made.
10321034
"""
10331035

1036+
# Regression test for https://github.com/wp-cli/search-replace-command/issues/68
1037+
Scenario: Incomplete classes are handled gracefully during (un)serialization
1038+
1039+
Given a WP install
1040+
And I run `wp option add cereal_isation 'a:1:{i:0;O:10:"CornFlakes":0:{}}'`
1041+
1042+
When I try `wp search-replace CornFlakes Smacks`
1043+
Then STDERR should contain:
1044+
"""
1045+
Warning: Skipping an uninitialized class "CornFlakes", replacements might not be complete.
1046+
"""
1047+
And STDOUT should contain:
1048+
"""
1049+
Success: Made 0 replacements.
1050+
"""
1051+
1052+
When I run `wp option get cereal_isation`
1053+
Then STDOUT should contain:
1054+
"""
1055+
a:1:{i:0;O:10:"CornFlakes":0:{}}
1056+
"""
1057+
10341058
Scenario: Regex search/replace with `--regex-limit=1` option
10351059
Given a WP install
10361060
And I run `wp post create --post_content="I have a pen, I have an apple. Pen, pine-apple, apple-pen."`
@@ -1050,4 +1074,4 @@ Feature: Do global search/replace
10501074
Then STDOUT should contain:
10511075
"""
10521076
I have a pen, I have an orange. Pen, pine-orange, apple-pen.
1053-
"""
1077+
"""

src/WP_CLI/SearchReplacer.php

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace WP_CLI;
44

5+
use ArrayObject;
6+
use Exception;
7+
58
class SearchReplacer {
69

710
private $from, $to;
@@ -90,9 +93,19 @@ private function _run( $data, $serialised, $recursion_level = 0, $visited_data =
9093
}
9194
}
9295

93-
elseif ( $this->recurse_objects && is_object( $data ) ) {
94-
foreach ( $data as $key => $value ) {
95-
$data->$key = $this->_run( $value, false, $recursion_level + 1, $visited_data );
96+
elseif ( $this->recurse_objects && ( is_object( $data ) || $data instanceof \__PHP_Incomplete_Class ) ) {
97+
if ( $data instanceof \__PHP_Incomplete_Class ) {
98+
$array = new ArrayObject( $data );
99+
\WP_CLI::warning(
100+
sprintf(
101+
'Skipping an uninitialized class "%s", replacements might not be complete.',
102+
$array['__PHP_Incomplete_Class_Name']
103+
)
104+
);
105+
} else {
106+
foreach ( $data as $key => $value ) {
107+
$data->$key = $this->_run( $value, false, $recursion_level + 1, $visited_data );
108+
}
96109
}
97110
}
98111

@@ -105,7 +118,17 @@ private function _run( $data, $serialised, $recursion_level = 0, $visited_data =
105118
$search_regex .= $this->from;
106119
$search_regex .= $this->regex_delimiter;
107120
$search_regex .= $this->regex_flags;
108-
$data = preg_replace( $search_regex, $this->to, $data, $this->regex_limit );
121+
122+
$result = preg_replace( $search_regex, $this->to, $data, $this->regex_limit );
123+
if ( null === $result || PREG_NO_ERROR !== preg_last_error() ) {
124+
\WP_CLI::warning(
125+
sprintf(
126+
'The provided regular expression threw a PCRE error - %s',
127+
$this->preg_error_message( $result )
128+
)
129+
);
130+
}
131+
$data = $result;
109132
} else {
110133
$data = str_replace( $this->from, $this->to, $data );
111134
}
@@ -138,5 +161,27 @@ public function get_log_data() {
138161
public function clear_log_data() {
139162
$this->log_data = array();
140163
}
164+
165+
/**
166+
* Get the PCRE error constant name from an error value.
167+
*
168+
* @param integer $error Error code.
169+
* @return string Error constant name.
170+
*/
171+
private function preg_error_message( $error ) {
172+
static $error_names = null;
173+
174+
if ( null === $error_names ) {
175+
$definitions = get_defined_constants( true );
176+
$pcre_constants = array_key_exists( 'pcre', $definitions )
177+
? $definitions['pcre']
178+
: array();
179+
$error_names = array_flip( $pcre_constants );
180+
}
181+
182+
return isset( $error_names[ $error ] )
183+
? $error_names[ $error ]
184+
: '<unknown error>';
185+
}
141186
}
142187

0 commit comments

Comments
 (0)