API: Work around PHP bug 45959
authorBrad Jorsch <bjorsch@wikimedia.org>
Thu, 14 Jan 2016 21:11:44 +0000 (16:11 -0500)
committerBrad Jorsch <bjorsch@wikimedia.org>
Thu, 14 Jan 2016 21:13:04 +0000 (16:13 -0500)
Sigh, PHP. You allow for an array to have string "1" as a key (e.g. when
casting from object to array), but then you do everything wrong when
trying to deal with it.

Bug: T123663
Change-Id: I49f09901a69aab39ca1519bbe9e41267bf9a1216

includes/api/ApiResult.php
tests/phpunit/includes/api/ApiResultTest.php

index bd5fe08..71af80c 100644 (file)
@@ -364,9 +364,13 @@ class ApiResult implements ApiSerializable {
                        }
                }
                if ( is_array( $value ) ) {
+                       // Work around PHP bug 45959 by copying to a temporary
+                       // (in this case, foreach gets $k === "1" but $tmp[$k] assigns as if $k === 1)
+                       $tmp = array();
                        foreach ( $value as $k => $v ) {
-                               $value[$k] = self::validateValue( $v );
+                               $tmp[$k] = self::validateValue( $v );
                        }
+                       $value = $tmp;
                } elseif ( is_float( $value ) && !is_finite( $value ) ) {
                        throw new InvalidArgumentException( "Cannot add non-finite floats to ApiResult" );
                } elseif ( is_string( $value ) ) {
index 9dbde3d..292d276 100644 (file)
@@ -218,6 +218,17 @@ class ApiResultTest extends MediaWikiTestCase {
                        0 => "foo\xef\xbf\xbdbar",
                        1 => "\xc3\xa1",
                ), $arr );
+
+               $obj = new stdClass;
+               $obj->{'1'} = 'one';
+               $arr = array();
+               ApiResult::setValue( $arr, 'foo', $obj );
+               $this->assertSame( array(
+                       'foo' => array(
+                               1 => 'one',
+                               ApiResult::META_TYPE => 'assoc',
+                       )
+               ), $arr );
        }
 
        /**
@@ -509,6 +520,19 @@ class ApiResultTest extends MediaWikiTestCase {
                        1 => "\xc3\xa1",
                        ApiResult::META_TYPE => 'assoc',
                ), $result->getResultData() );
+
+               $result = new ApiResult( 8388608 );
+               $obj = new stdClass;
+               $obj->{'1'} = 'one';
+               $arr = array();
+               $result->addValue( $arr, 'foo', $obj );
+               $this->assertSame( array(
+                       'foo' => array(
+                               1 => 'one',
+                               ApiResult::META_TYPE => 'assoc',
+                       ),
+                       ApiResult::META_TYPE => 'assoc',
+               ), $result->getResultData() );
        }
 
        /**