Skip to content

Commit 4fae0da

Browse files
Copilotswissspidy
andauthored
Handle array-like unserialized objects without dynamic property writes (#237)
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent db2d3e1 commit 4fae0da

2 files changed

Lines changed: 39 additions & 1 deletion

File tree

features/search-replace.feature

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,38 @@ Feature: Do global search/replace
12031203
a:1:{i:0;O:10:"CornFlakes":0:{}}
12041204
"""
12051205

1206+
Scenario: Search-replace updates iterable dictionary objects without dynamic property deprecations
1207+
1208+
Given a WP install
1209+
And a search-replace-case-insensitive-dictionary.php file:
1210+
"""
1211+
<?php
1212+
WP_CLI::add_hook( 'search_replace_unserialize_options', function() {
1213+
return [ 'allowed_classes' => [ 'stdClass', 'WpOrg\Requests\Utility\CaseInsensitiveDictionary' ] ];
1214+
} );
1215+
$replacer = new \WP_CLI\SearchReplacer( 'old.example.com', 'new.example.com', true );
1216+
echo $replacer->run(
1217+
serialize(
1218+
new \WpOrg\Requests\Utility\CaseInsensitiveDictionary(
1219+
[
1220+
'date' => 'https://old.example.com/feed',
1221+
]
1222+
)
1223+
)
1224+
);
1225+
"""
1226+
1227+
When I run `wp eval-file search-replace-case-insensitive-dictionary.php`
1228+
Then STDERR should be empty
1229+
And STDOUT should contain:
1230+
"""
1231+
https://new.example.com/feed
1232+
"""
1233+
And STDOUT should not contain:
1234+
"""
1235+
https://old.example.com/feed
1236+
"""
1237+
12061238
@require-mysql
12071239
Scenario: The search_replace_unserialize_options hook allows overriding allowed_classes for unserialize
12081240

src/WP_CLI/SearchReplacer.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,14 @@ private function run_recursively( $data, $serialised, $recursion_level = 0, $vis
195195
);
196196
} else {
197197
try {
198+
$is_array_access = $data instanceof \ArrayAccess;
198199
foreach ( $data as $key => $value ) {
199-
$data->$key = $this->run_recursively( $value, false, $recursion_level + 1, $visited_data );
200+
$value = $this->run_recursively( $value, false, $recursion_level + 1, $visited_data );
201+
if ( $is_array_access ) {
202+
$data[ $key ] = $value;
203+
} else {
204+
$data->$key = $value;
205+
}
200206
}
201207
} catch ( \Error $exception ) { // phpcs:ignore PHPCompatibility.Classes.NewClasses.errorFound
202208
// This error is thrown when the object that was unserialized cannot be iterated upon.

0 commit comments

Comments
 (0)