wfArrayToCGI() and wfCgiToArray() now handle nested and associative arrays almost...
authorMatěj Grabovský <mgrabovsky@users.mediawiki.org>
Thu, 23 Jun 2011 15:25:07 +0000 (15:25 +0000)
committerMatěj Grabovský <mgrabovsky@users.mediawiki.org>
Thu, 23 Jun 2011 15:25:07 +0000 (15:25 +0000)
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
includes/GlobalFunctions.php
tests/phpunit/includes/GlobalTest.php

index e8d54df..4625e78 100644 (file)
@@ -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.
index 2871676..bca5ca0 100644 (file)
@@ -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;
 }
index 5e6ae84..b06dbf1 100644 (file)
@@ -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() {