From 09da27efa2cacb16252fb43f4ec11d0a118e7129 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mat=C4=9Bj=20Grabovsk=C3=BD?= Date: Thu, 23 Jun 2011 15:25:07 +0000 Subject: [PATCH] wfArrayToCGI() and wfCgiToArray() now handle nested and associative arrays almost correctly The only problem is that all the indexes have to be set, thus "key[]=value" won't get parsed correctly and array( 'key' => array( 'value' ) ) will transform to "key[0]=value". Related bug 28928 and bug 22989. --- RELEASE-NOTES-1.19 | 2 ++ includes/GlobalFunctions.php | 43 ++++++++++++++++++++------- tests/phpunit/includes/GlobalTest.php | 12 ++++++++ 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/RELEASE-NOTES-1.19 b/RELEASE-NOTES-1.19 index e8d54df0df..4625e78100 100644 --- a/RELEASE-NOTES-1.19 +++ b/RELEASE-NOTES-1.19 @@ -115,6 +115,8 @@ production. * (bug 29507) Change 'image link' to 'file link' in Special:Whatlinkshere * If the db is really screwed up, and doesn't have a recentchanges table, make the updater throw an exception instead of a fatal. +* wfArrayToCGI() and wfCgiToArray() now handle nested and associative arrays + correctly === API changes in 1.19 === * BREAKING CHANGE: action=watch now requires POST and token. diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 2871676112..bca5ca0cdc 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -318,9 +318,10 @@ function wfUrlencode( $s ) { * * @param $array1 Array( String|Array ) * @param $array2 Array( String|Array ) + * @param $prefix String * @return String */ -function wfArrayToCGI( $array1, $array2 = null ) { +function wfArrayToCGI( $array1, $array2 = null, $prefix = '' ) { if ( !is_null( $array2 ) ) { $array1 = $array1 + $array2; } @@ -331,20 +332,25 @@ function wfArrayToCGI( $array1, $array2 = null ) { if ( $cgi != '' ) { $cgi .= '&'; } + if ( $prefix !== '' ) { + $key = $prefix . "[$key]"; + } if ( is_array( $value ) ) { $firstTime = true; - foreach ( $value as $v ) { - $cgi .= ( $firstTime ? '' : '&') . - urlencode( $key . '[]' ) . '=' . - urlencode( $v ); + foreach ( $value as $k => $v ) { + $cgi .= $firstTime ? '' : '&'; + if ( is_array( $v ) ) { + $cgi .= wfArrayToCGI( $v, null, $key . "[$k]" ); + } else { + $cgi .= urlencode( $key . "[$k]" ) . '=' . urlencode( $v ); + } $firstTime = false; } } else { if ( is_object( $value ) ) { $value = $value->__toString(); } - $cgi .= urlencode( $key ) . '=' . - urlencode( $value ); + $cgi .= urlencode( $key ) . '=' . urlencode( $value ); } } } @@ -362,19 +368,34 @@ function wfArrayToCGI( $array1, $array2 = null ) { * @return array Array version of input */ function wfCgiToArray( $query ) { - if( isset( $query[0] ) && $query[0] == '?' ) { + if ( isset( $query[0] ) && $query[0] == '?' ) { $query = substr( $query, 1 ); } $bits = explode( '&', $query ); $ret = array(); - foreach( $bits as $bit ) { - if( $bit === '' ) { + foreach ( $bits as $bit ) { + if ( $bit === '' ) { continue; } list( $key, $value ) = explode( '=', $bit ); $key = urldecode( $key ); $value = urldecode( $value ); - $ret[$key] = $value; + if ( strpos( $key, '[' ) !== false ) { + $keys = array_reverse( explode( '[', $key ) ); + $key = array_pop( $keys ); + $temp = $value; + foreach ( $keys as $k ) { + $k = substr( $k, 0, -1 ); + $temp = array( $k => $temp ); + } + if ( isset( $ret[$key] ) ) { + $ret[$key] = array_merge( $ret[$key], $temp ); + } else { + $ret[$key] = $temp; + } + } else { + $ret[$key] = $value; + } } return $ret; } diff --git a/tests/phpunit/includes/GlobalTest.php b/tests/phpunit/includes/GlobalTest.php index 5e6ae847c5..b06dbf1509 100644 --- a/tests/phpunit/includes/GlobalTest.php +++ b/tests/phpunit/includes/GlobalTest.php @@ -102,6 +102,18 @@ class GlobalTest extends MediaWikiTestCase { wfArrayToCGI( array( 'baz' => 'AT&T', 'ignore' => '' ), array( 'foo' => 'bar', 'baz' => 'overridden value' ) ) ); + $this->assertEquals( + "path%5B0%5D=wiki&path%5B1%5D=test&cfg%5Bservers%5D%5Bhttp%5D=localhost", + wfArrayToCGI( array( + 'path' => array( 'wiki', 'test' ), + 'cfg' => array( 'servers' => array( 'http' => 'localhost' ) ) ) ) ); + } + + function testCgiToArray() { + $this->assertEquals( + array( 'path' => array( 'wiki', 'test' ), + 'cfg' => array( 'servers' => array( 'http' => 'localhost' ) ) ), + wfCgiToArray( 'path%5B0%5D=wiki&path%5B1%5D=test&cfg%5Bservers%5D%5Bhttp%5D=localhost' ) ); } function testMimeTypeMatch() { -- 2.20.1