Fixing up a variety of GlobalFunctions and also improving queries in Titke.php.
authorDaniel Friesen <dantman@users.mediawiki.org>
Fri, 9 May 2008 23:36:21 +0000 (23:36 +0000)
committerDaniel Friesen <dantman@users.mediawiki.org>
Fri, 9 May 2008 23:36:21 +0000 (23:36 +0000)
* getFullURL and getLocalUrl now accept arrays and objects as valid input.
* Use wfAppendQuery in getLocalUrl to match up with getFullURL.
* wfArrayToCgi is now a alias to wfBuildQuery (Parameters are in the OPPOSITE order so wfBuildQuery takes defaults as second param and wfArrayToCgi takes them as first parameter like it always did)
* New function wfBuildQuery.
** The code moved here from what once was wfArrayToCgi has been changed from a set of plain loops to a wrapper around http_build_query so that complex data is handled correctly.
** We now support strings and objects as input, and we even parse strings when necessary to merge queries.
* New function wfForeignWikiID to pair with wfWikiID like wfForeignMemcKey. The foreign id can take 2 parameters, if omitted it falls back to the shared db, then to the local db if not set.
* wfMemcKey and wfForeignMemcKey now call the respective wf(Foreign)WikiID function, this simplifies the functions, and avoids code duplication making sure things always match even if for some strange reason it's changed.

I'll likely be using the forign functions later to improve the use of a shared interwiki map to avoid redundant caches.

I could always make the local MemcKey and WikiID functions depend on the foreign ones in a sane way

includes/GlobalFunctions.php
includes/Title.php

index e84e82c..0cd02fa 100644 (file)
@@ -983,25 +983,40 @@ function wfSetBit( &$dest, $bit, $state = true ) {
 }
 
 /**
- * This function takes two arrays as input, and returns a CGI-style string, e.g.
+ * This function takes one or two arrays, objects, or strings as input, and returns a CGI-style string, e.g.
  * "days=7&limit=100". Options in the first array override options in the second.
  * Options set to "" will not be output.
- */
-function wfArrayToCGI( $array1, $array2 = NULL )
-{
-       if ( !is_null( $array2 ) ) {
-               $array1 = $array1 + $array2;
-       }
-
-       $cgi = '';
-       foreach ( $array1 as $key => $value ) {
-               if ( '' !== $value ) {
-                       if ( '' != $cgi ) {
-                               $cgi .= '&';
+ * @depreciated
+ */
+function wfArrayToCGI( $query1, $query2 = null ) {
+       if( is_null($query2) ) wfBuildQuery( $query1 );
+       else wfBuildQuery( $query2, $query1 );
+}
+/**
+ * wfBuildQuery is a improved wrapper for http_build_query.
+ * We support a defaults array which the query may be merged with. As well we also support
+ * arrays, objects, and strings as input.
+ */
+function wfBuildQuery( $query, $defaults = null ) {
+       if( !is_null($defaults) ) {
+               ## If either array is a string, then parse it and make sure to fix magic quotes.
+               foreach( array( 'query', 'defaults' ) as $var ) {
+                       if( is_string($$var) ) {
+                               $arr = array();
+                               parse_str($$var, &$arr);
+                               if( function_exists( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc() ) {
+                                       global $wgRequest;
+                                       $wgRequest->fix_magic_quotes( $arr );
+                               }
+                               $$var = $arr;
                        }
-                       $cgi .= urlencode( $key ) . '=' . urlencode( $value );
                }
+               # Merge, make sure they are arrays, not objects.
+               $query = ((array)$defaults) + ((array)$query);
        }
+       
+       # Note that we must specify & because the default is sometimes &amp;
+       $cgi = is_string($query) ? $query : http_build_query( $query, null, '&' );
        return $cgi;
 }
 
@@ -2337,13 +2352,8 @@ function wfFormatStackFrame($frame) {
  * Get a cache key
  */
 function wfMemcKey( /*... */ ) {
-       global $wgDBprefix, $wgDBname;
        $args = func_get_args();
-       if ( $wgDBprefix ) {
-               $key = "$wgDBname-$wgDBprefix:" . implode( ':', $args );
-       } else {
-               $key = $wgDBname . ':' . implode( ':', $args );
-       }
+       $key = wfWikiID() . ':' . implode( ':', $args );
        return $key;
 }
 
@@ -2352,11 +2362,7 @@ function wfMemcKey( /*... */ ) {
  */
 function wfForeignMemcKey( $db, $prefix /*, ... */ ) {
        $args = array_slice( func_get_args(), 2 );
-       if ( $prefix ) {
-               $key = "$db-$prefix:" . implode( ':', $args );
-       } else {
-               $key = $db . ':' . implode( ':', $args );
-       }
+       wfForeignWikiID($db,$prefix) . ':' . implode( ':', $args );
        return $key;
 }
 
@@ -2365,7 +2371,7 @@ function wfForeignMemcKey( $db, $prefix /*, ... */ ) {
  * This is used as a prefix in memcached keys
  */
 function wfWikiID() {
-       global $wgDBprefix, $wgDBname;
+       global $wgDBname, wgDBprefix;
        if ( $wgDBprefix ) {
                return "$wgDBname-$wgDBprefix";
        } else {
@@ -2373,6 +2379,22 @@ function wfWikiID() {
        }
 }
 
+/**
+ * Get an ASCII string identifying a foreign wiki or shared db
+ * This is used as a prefix in foreign memcached keys
+ */
+function wfForeignWikiID( $db = null, $prefix = null ) {
+       global $wgSharedDB, $wgSharedPrefix, $wgDBname, $wgDBprefix;
+       if( !isset($db) ) $db = (isset($wgSharedDB) ? $wgSharedDB, $wgDBname);
+       if( !isset($prefix) ) $prefix = ($wgSharedPrefix ? $wgSharedPrefix, $wgDBprefix);
+       
+       if ( $prefix ) {
+               return "$db-$prefix";
+       } else {
+               return $db;
+       }
+}
+
 /**
  * Split a wiki ID into DB name and table prefix
  */
index 9dc3b4e..b4978c9 100644 (file)
@@ -761,10 +761,12 @@ class Title {
         */
        public function getFullURL( $query = '', $variant = false ) {
                global $wgContLang, $wgServer, $wgRequest;
-
+               
+               $query = wfBuildQuery( $query ); # Support query input other than strings.
+               
                if ( '' == $this->mInterwiki ) {
                        $url = $this->getLocalUrl( $query, $variant );
-
+                       
                        // Ugly quick hack to avoid duplicate prefixes (bug 4571 etc)
                        // Correct fix would be to move the prepending elsewhere.
                        if ($wgRequest->getVal('action') != 'render') {
@@ -772,7 +774,7 @@ class Title {
                        }
                } else {
                        $baseUrl = $this->getInterwikiLink( $this->mInterwiki );
-
+                       
                        $namespace = wfUrlencode( $this->getNsText() );
                        if ( '' != $namespace ) {
                                # Can this actually happen? Interwikis shouldn't be parsed.
@@ -801,14 +803,16 @@ class Title {
        public function getLocalURL( $query = '', $variant = false ) {
                global $wgArticlePath, $wgScript, $wgServer, $wgRequest;
                global $wgVariantArticlePath, $wgContLang, $wgUser;
-
+               
+               $query = wfBuildQuery( $query ); # Support query input other than strings.
+               
                // internal links should point to same variant as current page (only anonymous users)
                if($variant == false && $wgContLang->hasVariants() && !$wgUser->isLoggedIn()){
                        $pref = $wgContLang->getPreferredVariant(false);
                        if($pref != $wgContLang->getCode())
                                $variant = $pref;
                }
-
+               
                if ( $this->isExternal() ) {
                        $url = $this->getFullURL();
                        if ( $query ) {
@@ -844,7 +848,7 @@ class Title {
                                                $query = $matches[1];
                                                if( isset( $matches[4] ) ) $query .= $matches[4];
                                                $url = str_replace( '$1', $dbkey, $wgActionPaths[$action] );
-                                               if( $query != '' ) $url .= '?' . $query;
+                                               $url = wfAppendQuery( $url, $query );
                                        }
                                }
                                if ( $url === false ) {
@@ -854,7 +858,7 @@ class Title {
                                        $url = "{$wgScript}?title={$dbkey}&{$query}";
                                }
                        }
-
+                       
                        // FIXME: this causes breakage in various places when we
                        // actually expected a local URL and end up with dupe prefixes.
                        if ($wgRequest->getVal('action') == 'render') {