*/
private $mwGlobalsToUnset = [];
+ /**
+ * Holds original contents of interwiki table
+ * @var IResultWrapper
+ */
+ private $interwikiTable = null;
+
/**
* Holds original loggers which have been replaced by setLogger()
* @var LoggerInterface[]
* MediaWikiServices.
* @return MediaWikiServices
*/
- protected static function resetGlobalServices( Config $bootstrapConfig = null ) {
+ private static function resetGlobalServices( Config $bootstrapConfig = null ) {
$oldServices = MediaWikiServices::getInstance();
$oldConfigFactory = $oldServices->getConfigFactory();
$oldLoadBalancerFactory = $oldServices->getDBLoadBalancerFactory();
}
}
+ // Store contents of interwiki table in case it changes. Unfortunately, we seem to have no
+ // way to do this only when needed, because tablesUsed can be changed mid-test.
+ if ( $this->db ) {
+ $this->interwikiTable = $this->db->select( 'interwiki', '*', '', __METHOD__ );
+ }
+
// Reset all caches between tests.
$this->doLightweightServiceReset();
foreach ( $this->mwGlobalsToUnset as $value ) {
unset( $GLOBALS[$value] );
}
+ if (
+ array_key_exists( 'wgExtraNamespaces', $this->mwGlobals ) ||
+ in_array( 'wgExtraNamespaces', $this->mwGlobalsToUnset )
+ ) {
+ $this->resetNamespaces();
+ }
$this->mwGlobals = [];
$this->mwGlobalsToUnset = [];
$this->restoreLoggers();
return $object;
}
);
+
+ if ( $name === 'ContentLanguage' ) {
+ $this->doSetMwGlobals( [ 'wgContLang' => $object ] );
+ }
}
/**
$pairs = [ $pairs => $value ];
}
+ if ( isset( $pairs['wgContLang'] ) ) {
+ throw new MWException(
+ 'No setting $wgContLang, use setContentLang() or setService( \'ContentLanguage\' )'
+ );
+ }
+
+ $this->doSetMwGlobals( $pairs, $value );
+ }
+
+ /**
+ * An internal method that allows setService() to set globals that tests are not supposed to
+ * touch.
+ */
+ private function doSetMwGlobals( $pairs, $value = null ) {
$this->stashMwGlobals( array_keys( $pairs ) );
foreach ( $pairs as $key => $value ) {
$GLOBALS[$key] = $value;
}
+
+ if ( array_key_exists( 'wgExtraNamespaces', $pairs ) ) {
+ $this->resetNamespaces();
+ }
+ }
+
+ /**
+ * Must be called whenever namespaces are changed, e.g., $wgExtraNamespaces is altered.
+ * Otherwise old namespace data will lurk and cause bugs.
+ */
+ private function resetNamespaces() {
+ MWNamespace::clearCaches();
+ Language::clearCaches();
+
+ // We can't have the TitleFormatter holding on to an old Language object either
+ // @todo We shouldn't need to reset all the aliases here.
+ $services = MediaWikiServices::getInstance();
+ $services->resetServiceForTesting( 'TitleFormatter' );
+ $services->resetServiceForTesting( 'TitleParser' );
+ $services->resetServiceForTesting( '_MediaWikiTitleCodec' );
}
/**
* @return MediaWikiServices
* @throws MWException
*/
- protected function overrideMwServices( Config $configOverrides = null, array $services = [] ) {
+ protected static function overrideMwServices(
+ Config $configOverrides = null, array $services = []
+ ) {
if ( !$configOverrides ) {
$configOverrides = new HashConfig();
}
$langCode = $lang;
$langObj = Language::factory( $langCode );
}
- $this->setMwGlobals( [
- 'wgLanguageCode' => $langCode,
- 'wgContLang' => $langObj,
- ] );
+ $this->setMwGlobals( 'wgLanguageCode', $langCode );
+ $this->setService( 'ContentLanguage', $langObj );
}
/**
$user
);
// an edit always attempt to purge backlink links such as history
- // pages. That is unneccessary.
+ // pages. That is unnecessary.
JobQueueGroup::singleton()->get( 'htmlCacheUpdate' )->delete();
// WikiPages::doEditUpdates randomly adds RC purges
JobQueueGroup::singleton()->get( 'recentChangesUpdate' )->delete();
$truncate = in_array( $db->getType(), [ 'oracle', 'mysql' ] );
foreach ( $tablesUsed as $tbl ) {
- // TODO: reset interwiki table to its original content.
- if ( $tbl == 'interwiki' ) {
- continue;
- }
-
if ( !$db->tableExists( $tbl ) ) {
continue;
}
$db->resetSequenceForTable( $tbl, __METHOD__ );
}
+ if ( $tbl === 'interwiki' ) {
+ if ( !$this->interwikiTable ) {
+ // @todo We should probably throw here, but this causes test failures that I
+ // can't figure out, so for now we silently continue.
+ continue;
+ }
+ $db->insert(
+ 'interwiki',
+ array_values( array_map( 'get_object_vars', iterator_to_array( $this->interwikiTable ) ) ),
+ __METHOD__
+ );
+ }
+
if ( $tbl === 'page' ) {
// Forget about the pages since they don't
// exist in the DB.
return $loaded;
}
+ /**
+ * Skip the test if using the specified database type
+ *
+ * @param string $type Database type
+ * @since 1.32
+ */
+ protected function markTestSkippedIfDbType( $type ) {
+ if ( $this->db->getType() === $type ) {
+ $this->markTestSkipped( "The $type database type isn't supported for this test" );
+ }
+ }
+
/**
* Used as a marker to prevent wfResetOutputBuffers from breaking PHPUnit.
* @param string $buffer
}
self::assertEquals( file_get_contents( $fileName ), $actualData, $msg );
}
+
+ /**
+ * Edits or creates a page/revision
+ * @param string $pageName Page title
+ * @param string $text Content of the page
+ * @param string $summary Optional summary string for the revision
+ * @param int $defaultNs Optional namespace id
+ * @return array Array as returned by WikiPage::doEditContent()
+ */
+ protected function editPage( $pageName, $text, $summary = '', $defaultNs = NS_MAIN ) {
+ $title = Title::newFromText( $pageName, $defaultNs );
+ $page = WikiPage::factory( $title );
+
+ return $page->doEditContent( ContentHandler::makeContent( $text, $title ), $summary );
+ }
+
+ /**
+ * Revision-deletes a revision.
+ *
+ * @param Revision|int $rev Revision to delete
+ * @param array $value Keys are Revision::DELETED_* flags. Values are 1 to set the bit, 0 to
+ * clear, -1 to leave alone. (All other values also clear the bit.)
+ * @param string $comment Deletion comment
+ */
+ protected function revisionDelete(
+ $rev, array $value = [ Revision::DELETED_TEXT => 1 ], $comment = ''
+ ) {
+ if ( is_int( $rev ) ) {
+ $rev = Revision::newFromId( $rev );
+ }
+ RevisionDeleter::createList(
+ 'revision', RequestContext::getMain(), $rev->getTitle(), [ $rev->getId() ]
+ )->setVisibility( [
+ 'value' => $value,
+ 'comment' => $comment,
+ ] );
+ }
}