Merge "Revert "Revert "Show a "(blocked)" hint on Special:ListUsers/ActiveUsers"""
[lhc/web/wiklou.git] / tests / phpunit / MediaWikiTestCase.php
index f9e9f77..5bc36ed 100644 (file)
@@ -29,6 +29,13 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         */
        private $tmpfiles = array();
 
+       /**
+        * Holds original values of MediaWiki configuration settings
+        * to be restored in tearDown().
+        * See also setMwGlobal().
+        * @var array
+        */
+       private $mwGlobals = array();
 
        /**
         * Table name prefixes. Oracle likes it shorter.
@@ -119,6 +126,41 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                return $fname;
        }
 
+       /**
+        * setUp and tearDown should (where significant)
+        * happen in reverse order.
+        */
+       protected function setUp() {
+               parent::setUp();
+
+               /*
+               //@todo: global variables to restore for *every* test
+               array(
+                       'wgLang',
+                       'wgContLang',
+                       'wgLanguageCode',
+                       'wgUser',
+                       'wgTitle',
+               );
+               */
+
+               // Cleaning up temporary files
+               foreach ( $this->tmpfiles as $fname ) {
+                       if ( is_file( $fname ) || ( is_link( $fname ) ) ) {
+                               unlink( $fname );
+                       } elseif ( is_dir( $fname ) ) {
+                               wfRecursiveRemoveDir( $fname );
+                       }
+               }
+
+               // Clean up open transactions
+               if ( $this->needsDB() && $this->db ) {
+                       while( $this->db->trxLevel() > 0 ) {
+                               $this->db->rollback();
+                       }
+               }
+       }
+
        protected function tearDown() {
                // Cleaning up temporary files
                foreach ( $this->tmpfiles as $fname ) {
@@ -129,16 +171,95 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        }
                }
 
-               // clean up open transactions
-               if( $this->needsDB() && $this->db ) {
+               // Clean up open transactions
+               if ( $this->needsDB() && $this->db ) {
                        while( $this->db->trxLevel() > 0 ) {
                                $this->db->rollback();
                        }
                }
 
+               // Restore mw globals
+               foreach ( $this->mwGlobals as $key => $value ) {
+                       $GLOBALS[$key] = $value;
+               }
+               $this->mwGlobals = array();
+
                parent::tearDown();
        }
 
+       /**
+        * Individual test functions may override globals (either directly or through this
+        * setMwGlobals() function), however one must call this method at least once for
+        * each key within the setUp().
+        * That way the key is added to the array of globals that will be reset afterwards
+        * in the tearDown(). And, equally important, that way all other tests are executed
+        * with the same settings (instead of using the unreliable local settings for most
+        * tests and fix it only for some tests).
+        *
+        * @example
+        * <code>
+        *     protected function setUp() {
+        *         $this->setMwGlobals( 'wgRestrictStuff', true );
+        *     }
+        *
+        *     function testFoo() {}
+        *
+        *     function testBar() {}
+        *         $this->assertTrue( self::getX()->doStuff() );
+        *
+        *         $this->setMwGlobals( 'wgRestrictStuff', false );
+        *         $this->assertTrue( self::getX()->doStuff() );
+        *     }
+        *
+        *     function testQuux() {}
+        * </code>
+        *
+        * @param array|string $pairs Key to the global variable, or an array
+        *  of key/value pairs.
+        * @param mixed $value Value to set the global to (ignored
+        *  if an array is given as first argument).
+        */
+       protected function setMwGlobals( $pairs, $value = null ) {
+               if ( !is_array( $pairs ) ) {
+                       $key = $pairs;
+                       $this->mwGlobals[$key] = $GLOBALS[$key];
+                       $GLOBALS[$key] = $value;
+               } else {
+                       foreach ( $pairs as $key => $value ) {
+                               $this->mwGlobals[$key] = $GLOBALS[$key];
+                               $GLOBALS[$key] = $value;
+                       }
+               }
+       }
+
+       /**
+        * Merges the given values into a MW global array variable.
+        * Useful for setting some entries in a configuration array, instead of
+        * setting the entire array.
+        *
+        * @param String $name The name of the global, as in wgFooBar
+        * @param Array $values The array containing the entries to set in that global
+        *
+        * @throws MWException if the designated global is not an array.
+        */
+       protected function mergeMwGlobalArrayValue( $name, $values ) {
+               if ( !isset( $GLOBALS[$name] ) ) {
+                       $merged = $values;
+               } else {
+                       if ( !is_array( $GLOBALS[$name] ) ) {
+                               throw new MWException( "MW global $name is not an array." );
+                       }
+
+                       //NOTE: do not use array_merge, it screws up for numeric keys.
+                       $merged = $GLOBALS[$name];
+                       foreach ( $values as $k => $v ) {
+                               $merged[$k] = $v;
+                       }
+               }
+
+               $this->setMwGlobals( $name, $merged );
+       }
+
        function dbPrefix() {
                return $this->db->getType() == 'oracle' ? self::ORA_DB_PREFIX : self::DB_PREFIX;
        }
@@ -212,11 +333,12 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                //Make 1 page with 1 revision
                $page = WikiPage::factory( Title::newFromText( 'UTPage' ) );
                if ( !$page->getId() == 0 ) {
-                       $page->doEdit( 'UTContent',
-                                                       'UTPageSummary',
-                                                       EDIT_NEW,
-                                                       false,
-                                                       User::newFromName( 'UTSysop' ) );
+                       $page->doEditContent(
+                               new WikitextContent( 'UTContent' ),
+                               'UTPageSummary',
+                               EDIT_NEW,
+                               false,
+                               User::newFromName( 'UTSysop' ) );
                }
        }
 
@@ -368,7 +490,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         *         or list the tables under testing in $this->tablesUsed, or override the
         *         needsDB() method.
         */
-       protected function assertSelect( $table, $fields, $condition, Array $expectedRows ) {
+       protected function assertSelect( $table, $fields, $condition, array $expectedRows ) {
                if ( !$this->needsDB() ) {
                        throw new MWException( 'When testing database state, the test cases\'s needDB()' .
                                ' method should return true. Use @group Database or $this->tablesUsed.');
@@ -544,4 +666,77 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                }
        }
 
+       /**
+        * Returns true iff the given namespace defaults to Wikitext
+        * according to $wgNamespaceContentModels
+        *
+        * @param int $ns The namespace ID to check
+        *
+        * @return bool
+        * @since 1.21
+        */
+       protected function isWikitextNS( $ns ) {
+               global $wgNamespaceContentModels;
+
+               if ( isset( $wgNamespaceContentModels[$ns] ) ) {
+                       return $wgNamespaceContentModels[$ns] === CONTENT_MODEL_WIKITEXT;
+               }
+
+               return true;
+       }
+
+       /**
+        * Returns the ID of a namespace that defaults to Wikitext.
+        * Throws an MWException if there is none.
+        *
+        * @return int the ID of the wikitext Namespace
+        * @since 1.21
+        */
+       protected function getDefaultWikitextNS() {
+               global $wgNamespaceContentModels;
+
+               static $wikitextNS = null; // this is not going to change
+               if ( $wikitextNS !== null ) {
+                       return $wikitextNS;
+               }
+
+               // quickly short out on most common case:
+               if ( !isset( $wgNamespaceContentModels[NS_MAIN] ) ) {
+                       return NS_MAIN;
+               }
+
+               // NOTE: prefer content namespaces
+               $namespaces = array_unique( array_merge(
+                       MWNamespace::getContentNamespaces(),
+                       array( NS_MAIN, NS_HELP, NS_PROJECT ), // prefer these
+                       MWNamespace::getValidNamespaces()
+               ) );
+
+               $namespaces = array_diff( $namespaces, array(
+                       NS_FILE, NS_CATEGORY, NS_MEDIAWIKI, NS_USER // don't mess with magic namespaces
+               ));
+
+               $talk = array_filter( $namespaces, function ( $ns ) {
+                       return MWNamespace::isTalk( $ns );
+               } );
+
+               // prefer non-talk pages
+               $namespaces = array_diff( $namespaces, $talk );
+               $namespaces = array_merge( $namespaces, $talk );
+
+               // check default content model of each namespace
+               foreach ( $namespaces as $ns ) {
+                       if ( !isset( $wgNamespaceContentModels[$ns] ) ||
+                               $wgNamespaceContentModels[$ns] === CONTENT_MODEL_WIKITEXT ) {
+
+                               $wikitextNS = $ns;
+                               return $wikitextNS;
+                       }
+               }
+
+               // give up
+               // @todo: Inside a test, we could skip the test as incomplete.
+               //        But frequently, this is used in fixture setup.
+               throw new MWException( "No namespace defaults to wikitext!" );
+       }
 }