* Rewrote wfArrayMerge() in terms of array plus
authorTim Starling <tstarling@users.mediawiki.org>
Sat, 1 Nov 2008 23:20:25 +0000 (23:20 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Sat, 1 Nov 2008 23:20:25 +0000 (23:20 +0000)
* Two callers of wfArrayMerge() were bugs, both assuming strange and complex behaviour in wfArrayMerge() which has never been present or documented.
* Introduced wfMergeErrorArrays() to remove duplicates from merged error arrays, e.g. from getUserPermissionsErrors().
* Rewrote the remaining callers of wfArrayMerge() to use array plus. It makes the code clearer, assuming the reader knows more about basic PHP operators than GlobalFunctions.php. Considering the two bugs discussed above, this seems like a fair assumption. If you don't know PHP, you shouldn't be writing MediaWiki code.

includes/GlobalFunctions.php
includes/OutputPage.php
includes/Title.php
includes/WebRequest.php
includes/specials/SpecialIpblocklist.php
includes/specials/SpecialRecentchanges.php
languages/Language.php

index 616c7a7..67c64c9 100644 (file)
@@ -1044,7 +1044,7 @@ function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) {
  */
 function wfEscapeWikiText( $text ) {
        $text = str_replace(
-               array( '[',     '|',      ']',     '\'',    'ISBN ',     'RFC ',     '://',     "\n=",     '{{' ),
+               array( '[',     '|',      ']',     '\'',    'ISBN ',     'RFC ',     '://',     "\n=",     '{{' ), # }}
                array( '&#91;', '&#124;', '&#93;', '&#39;', 'ISBN&#32;', 'RFC&#32;', '&#58;//', "\n&#61;", '&#123;&#123;' ),
                htmlspecialchars($text) );
        return $text;
@@ -2320,30 +2320,50 @@ function wfRelativePath( $path, $from ) {
 }
 
 /**
- * Like array_merge(), but always applying the behavior for string
- * keys. array_merge() has inconsistent behavior when your string
- * indexes happen to look like integers, which is undesireable
- * for arbitrary input.
- *
- * This is roughly equivalent to $array1 + $array2 + $array3...
- * but has different behavior when there are conflicts.
- *
- * array_merge() and wfArrayMerge() take the right-hand value,
- * whereas the + operator takes the left-hand value.
+ * Backwards array plus for people who haven't bothered to read the PHP manual
+ * XXX: will not darn your socks for you.
  *
  * @param array $array1, [$array2, [...]]
  * @return array
  */
 function wfArrayMerge( $array1/* ... */ ) {
-       $out = $array1;
-       for( $i = 1; $i < func_num_args(); $i++ ) {
-               foreach( func_get_arg( $i ) as $key => $value ) {
-                       $out[$key] = $value;
-               }
+       $args = func_get_args();
+       $args = array_reverse( $args, true );
+       $out = array();
+       foreach ( $args as $arg ) {
+               $out += $arg;
        }
        return $out;
 }
 
+/**
+ * Merge arrays in the style of getUserPermissionsErrors, with duplicate removal
+ * e.g.
+ *     wfMergeErrorArrays( 
+ *             array( array( 'x' ) ), 
+ *             array( array( 'x', '2' ) ), 
+ *             array( array( 'x' ) ), 
+ *             array( array( 'y') )
+ *     );
+ * returns:
+ *             array( 
+ *             array( 'x', '2' ),
+ *             array( 'x' ),
+ *             array( 'y' )
+ *     )
+ */
+function wfMergeErrorArrays(/*...*/) {
+       $args = func_get_args();
+       $out = array();
+       foreach ( $args as $errors ) {
+               foreach ( $errors as $params ) {
+                       $spec = implode( "\t", $params );
+                       $out[$spec] = $params;
+               }
+       }
+       return array_values( $out );
+}
+
 /**
  * Make a URL index, appropriate for the el_index field of externallinks.
  */
index 74feac9..99b7aaf 100644 (file)
@@ -531,8 +531,13 @@ class OutputPage {
                $this->mNoGallery = $parserOutput->getNoGallery();
                $this->mHeadItems = array_merge( $this->mHeadItems, (array)$parserOutput->mHeadItems );
                // Versioning...
-               $this->mTemplateIds = wfArrayMerge( $this->mTemplateIds, (array)$parserOutput->mTemplateIds );
-
+               foreach ( (array)$parserOutput->mTemplateIds as $ns => $dbks ) {
+                       if ( isset( $this->mTemplateIds[$ns] ) ) {
+                               $this->mTemplateIds[$ns] = $dbks + $this->mTemplateIds[$ns];
+                       } else {
+                               $this->mTemplateIds[$ns] = $dbks;
+                       }
+               }
                // Display title
                if( ( $dt = $parserOutput->getDisplayTitle() ) !== false )
                        $this->setPageTitle( $dt );
index eb9e2b1..8feb6b0 100644 (file)
@@ -2468,11 +2468,11 @@ class Title {
                }
 
                if ( $auth ) {
-                       $errors = wfArrayMerge($errors, 
-                                       $this->getUserPermissionsErrors('move', $wgUser),
-                                       $this->getUserPermissionsErrors('edit', $wgUser),
-                                       $nt->getUserPermissionsErrors('move-target', $wgUser),
-                                       $nt->getUserPermissionsErrors('edit', $wgUser));
+                       $errors = wfMergeErrorArrays( $errors,
+                               $this->getUserPermissionsErrors('move', $wgUser),
+                               $this->getUserPermissionsErrors('edit', $wgUser),
+                               $nt->getUserPermissionsErrors('move-target', $wgUser),
+                               $nt->getUserPermissionsErrors('edit', $wgUser) );
                }
 
                $match = EditPage::matchSpamRegex( $reason );
index 9d9f10d..4674712 100644 (file)
@@ -55,7 +55,7 @@ class WebRequest {
 
                // POST overrides GET data
                // We don't use $_REQUEST here to avoid interference from cookies...
-               $this->data = wfArrayMerge( $_GET, $_POST );
+               $this->data = $_POST + $_GET;
        }
 
        /**
index 3e44f68..cd28b66 100644 (file)
@@ -357,7 +357,7 @@ class IPUnblockForm {
        function makeOptionsLink( $title, $override, $options, $active = false ) {
                global $wgUser;
                $sk = $wgUser->getSkin();
-               $params = wfArrayMerge( $options, $override );
+               $params = $options + $override;
                $ipblocklist = SpecialPage::getTitleFor( 'IPBlockList' );
                return $sk->link( $ipblocklist, htmlspecialchars( $title ),
                        ( $active ? array( 'style'=>'font-weight: bold;' ) : array() ), $params, array( 'known' ) );
index 11f9864..71cc678 100644 (file)
@@ -580,7 +580,7 @@ class SpecialRecentChanges extends SpecialPage {
        function makeOptionsLink( $title, $override, $options, $active = false ) {
                global $wgUser;
                $sk = $wgUser->getSkin();
-               $params = wfArrayMerge( $options, $override );
+               $params = $override + $options;
                return $sk->link( $this->getTitle(), htmlspecialchars( $title ),
                        ( $active ? array( 'style'=>'font-weight: bold;' ) : array() ), $params, array( 'known' ) );
        }
index 5648f6c..78e71a0 100644 (file)
@@ -1761,7 +1761,7 @@ class Language {
                                        $aliases[$code] = $this->fixSpecialPageAliases( $aliases[$code] );
                                        /* Merge the aliases, THIS will break if there is special page name
                                        * which looks like a numerical key, thanks to PHP...
-                                       * See the comments for wfArrayMerge in GlobalSettings.php. */
+                                       * See the array_merge_recursive manual entry */
                                        $this->mExtendedSpecialPageAliases = array_merge_recursive(
                                                $this->mExtendedSpecialPageAliases, $aliases[$code] );