if ( '' === $row->$col )
continue;
- $value = self::recursive_unserialize_replace( $old, $new, $row->$col, false, $recurse_objects );
+ $value = WP_CLI\Utils\recursive_unserialize_replace( $old, $new, $row->$col, false, $recurse_objects );
if ( $dry_run ) {
if ( $value != $row->$col )
return $count;
}
- /**
- * Take a serialised array and unserialise it replacing elements as needed and
- * unserialising any subordinate arrays and performing the replace on those too.
- * Ignores any serialized objects unless $recurse_objects is set to true.
- *
- * Initial code from https://github.com/interconnectit/Search-Replace-DB
- *
- * @param string $from String we're looking to replace.
- * @param string $to What we want it to be replaced with
- * @param array|string $data Used to pass any subordinate arrays back to in.
- * @param bool $serialised Does the array passed via $data need serialising.
- * @param bool $recurse_objects Should objects be recursively replaced.
- * @param int $max_recursion How many levels to recurse into the data, if $recurse_objects is set to true.
- * @param int $recursion_level Current recursion depth within the original data.
- * @param array $visited_data Data that has been seen in previous recursion iterations.
- *
- * @return array The original array with all elements replaced as needed.
- */
- private static function recursive_unserialize_replace( $from = '', $to = '', &$data = '', $serialised = false, $recurse_objects = false, $max_recursion = -1, $recursion_level = 0, &$visited_data = array() ) {
-
- // some unseriliased data cannot be re-serialised eg. SimpleXMLElements
- try {
-
- if ( $recurse_objects ) {
-
- // If no maximum recursion level is set, use the XDebug limit if it exists
- if ( -1 == $max_recursion ) {
- // Get the XDebug nesting level. Will be zero (no limit) if no value is set
- $max_recursion = intval( ini_get( 'xdebug.max_nesting_level' ) );
- }
-
- // If we've reached the maximum recursion level, short circuit
- if ( $max_recursion != 0 && $recursion_level >= $max_recursion ) {
- WP_CLI::warning("Maximum recursion level of $max_recursion reached");
- return $data;
- }
-
- if ( ( is_array( $data ) || is_object( $data ) ) ) {
- // If we've seen this exact object or array before, short circuit
- if ( in_array( $data, $visited_data, true ) ) {
- return $data; // Avoid infinite loops when there's a cycle
- }
- // Add this data to the list of
- $visited_data[] = $data;
- }
- }
-
- if ( is_string( $data ) && ( $unserialized = @unserialize( $data ) ) !== false ) {
- $data = self::recursive_unserialize_replace( $from, $to, $unserialized, true, $recurse_objects, $max_recursion, $recursion_level + 1 );
- }
-
- elseif ( is_array( $data ) ) {
- $keys = array_keys( $data );
- foreach ( $keys as $key ) {
- $data[ $key ]= self::recursive_unserialize_replace( $from, $to, $data[$key], false, $recurse_objects, $max_recursion, $recursion_level + 1, $visited_data );
- }
- }
-
- elseif ( $recurse_objects && is_object( $data ) ) {
- foreach ( $data as $key => $value ) {
- $data->$key = self::recursive_unserialize_replace( $from, $to, $value, false, $recurse_objects, $max_recursion, $recursion_level + 1, $visited_data );
- }
- }
-
- else if ( is_string( $data ) ) {
- $data = str_replace( $from, $to, $data );
- }
-
- if ( $serialised )
- return serialize( $data );
-
- } catch( Exception $error ) {
-
- }
-
- return $data;
- }
-
private static function get_columns( $table ) {
global $wpdb;
return $url_parts;
}
+
+/**
+ * Take a serialised array and unserialise it replacing elements as needed and
+ * unserialising any subordinate arrays and performing the replace on those too.
+ * Ignores any serialized objects unless $recurse_objects is set to true.
+ *
+ * Initial code from https://github.com/interconnectit/Search-Replace-DB
+ *
+ * @param string $from String we're looking to replace.
+ * @param string $to What we want it to be replaced with
+ * @param array|string $data Used to pass any subordinate arrays back to in.
+ * @param bool $serialised Does the array passed via $data need serialising.
+ * @param bool $recurse_objects Should objects be recursively replaced.
+ * @param int $max_recursion How many levels to recurse into the data, if $recurse_objects is set to true.
+ * @param int $recursion_level Current recursion depth within the original data.
+ * @param array $visited_data Data that has been seen in previous recursion iterations.
+ *
+ * @return array The original array with all elements replaced as needed.
+ */
+function recursive_unserialize_replace( $from = '', $to = '', &$data = '', $serialised = false, $recurse_objects = false, $max_recursion = -1, $recursion_level = 0, &$visited_data = array() ) {
+
+ // some unseriliased data cannot be re-serialised eg. SimpleXMLElements
+ try {
+
+ if ( $recurse_objects ) {
+
+ // If no maximum recursion level is set, use the XDebug limit if it exists
+ if ( -1 == $max_recursion ) {
+ // Get the XDebug nesting level. Will be zero (no limit) if no value is set
+ $max_recursion = intval( ini_get( 'xdebug.max_nesting_level' ) );
+ }
+
+ // If we've reached the maximum recursion level, short circuit
+ if ( $max_recursion != 0 && $recursion_level >= $max_recursion ) {
+ return $data;
+ }
+
+ if ( ( is_array( $data ) || is_object( $data ) ) ) {
+ // If we've seen this exact object or array before, short circuit
+ if ( in_array( $data, $visited_data, true ) ) {
+ return $data; // Avoid infinite loops when there's a cycle
+ }
+ // Add this data to the list of
+ $visited_data[] = $data;
+ }
+ }
+
+ if ( is_string( $data ) && ( $unserialized = @unserialize( $data ) ) !== false ) {
+ $data = recursive_unserialize_replace( $from, $to, $unserialized, true, $recurse_objects, $max_recursion, $recursion_level + 1 );
+ }
+
+ elseif ( is_array( $data ) ) {
+ $keys = array_keys( $data );
+ foreach ( $keys as $key ) {
+ $data[ $key ]= recursive_unserialize_replace( $from, $to, $data[$key], false, $recurse_objects, $max_recursion, $recursion_level + 1, $visited_data );
+ }
+ }
+
+ elseif ( $recurse_objects && is_object( $data ) ) {
+ foreach ( $data as $key => $value ) {
+ $data->$key = recursive_unserialize_replace( $from, $to, $value, false, $recurse_objects, $max_recursion, $recursion_level + 1, $visited_data );
+ }
+ }
+
+ else if ( is_string( $data ) ) {
+ $data = str_replace( $from, $to, $data );
+ }
+
+ if ( $serialised )
+ return serialize( $data );
+
+ } catch( Exception $error ) {
+
+ }
+
+ return $data;
+}
+
--- /dev/null
+<?php
+
+require_once getcwd() . '/php/class-wp-cli.php';
+require_once getcwd() . '/php/class-wp-cli-command.php';
+require_once getcwd() . '/php/commands/search-replace.php';
+
+class UnserializeReplaceTest extends PHPUnit_Framework_TestCase {
+
+ function testReplaceString() {
+ $orig = 'foo';
+ $replacement = WP_CLI\Utils\recursive_unserialize_replace( 'foo', 'bar', $orig );
+ $this->assertEquals( 'bar', $replacement );
+ }
+
+ function testPrivateConstructor() {
+ $old_obj = ClassWithPrivateConstructor::get_instance();
+
+ $new_obj = WP_CLI\Utils\recursive_unserialize_replace( 'foo', 'bar', $old_obj, false, true );
+ $this->assertEquals( 'bar', $new_obj->prop );
+ }
+
+ function testObjectLoop() {
+ $old_object = new stdClass();
+ $old_object->prop = 'foo';
+ $old_object->self = $old_object;
+
+ $new_obj = WP_CLI\Utils\recursive_unserialize_replace( 'foo', 'bar', $old_object, false, true );
+ $this->assertEquals( 'bar', $new_obj->prop );
+ }
+
+ function testArrayLoop() {
+ $old_array = array( 'prop' => 'foo' );
+ $old_array['self'] = &$old_array;
+
+ $new_array = WP_CLI\Utils\recursive_unserialize_replace( 'foo', 'bar', $old_array, false, true );
+ $this->assertEquals( 'bar', $new_array['prop'] );
+ }
+
+ function testMixedObjectArrayLoop() {
+ $old_object = new stdClass();
+ $old_object->prop = 'foo';
+ $old_object->array = array('prop' => 'foo');
+ $old_object->array['object'] = $old_object;
+
+ $new_object = WP_CLI\Utils\recursive_unserialize_replace( 'foo', 'bar', $old_object, false, true );
+ $this->assertEquals( 'bar', $new_object->prop );
+ $this->assertEquals( 'bar', $new_object->array['prop']);
+ }
+
+ function testMixedArrayObjectLoop() {
+ $old_array = array( 'prop' => 'foo', 'object' => new stdClass() );
+ $old_array['object']->prop = 'foo';
+ $old_array['object']->array = &$old_array;
+
+ $new_array = WP_CLI\Utils\recursive_unserialize_replace( 'foo', 'bar', $old_array, false, true );
+ $this->assertEquals( 'bar', $new_array['prop'] );
+ $this->assertEquals( 'bar', $new_array['object']->prop);
+ }
+}
+
+
+class ClassWithPrivateConstructor {
+
+ public $prop = 'foo';
+
+ private function __construct() {}
+
+ public static function get_instance() {
+ return new self;
+ }
+}