Merge "Localisation updates from https://translatewiki.net."
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 15 Aug 2019 08:09:04 +0000 (08:09 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 15 Aug 2019 08:09:04 +0000 (08:09 +0000)
INSTALL
RELEASE-NOTES-1.34
autoload.php
includes/search/SearchEngineFactory.php
includes/search/SearchHighlighter.php
includes/search/SearchMssql.php [deleted file]
includes/search/SearchOracle.php [deleted file]
languages/i18n/en.json
languages/i18n/qqq.json
tests/phpunit/includes/TestUser.php

diff --git a/INSTALL b/INSTALL
index f31f753..bf64ab7 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -11,8 +11,6 @@ Required software:
 ** MySQL 5.5.8 or higher
 ** PostgreSQL 9.2 or higher
 ** SQLite 3.8.0 or higher
-** Oracle 9.0.1 or higher
-** Microsoft SQL Server 2005 (9.00.1399)
 
 MediaWiki is developed and tested mainly on Unix/Linux platforms, but should
 work on Windows as well.
index 69a64d0..9660e9e 100644 (file)
@@ -454,16 +454,13 @@ supported, it is generally advised to use PHP 7.0.13 or later for long term
 support.
 
 MySQL/MariaDB is the recommended DBMS. PostgreSQL or SQLite can also be used,
-but support for them is somewhat less mature. There is experimental support for
-Oracle and Microsoft SQL Server.
+but support for them is somewhat less mature.
 
 The supported versions are:
 
 * MySQL 5.5.8 or later
 * PostgreSQL 9.2 or later
 * SQLite 3.8.0 or later
-* Oracle 9.0.1 or later
-* Microsoft SQL Server 2005 (9.00.1399)
 
 == Online documentation ==
 Documentation for both end-users and site administrators is available on
index 9a555d0..52a5eda 100644 (file)
@@ -1308,11 +1308,9 @@ $wgAutoloadLocalClasses = [
        'SearchHighlighter' => __DIR__ . '/includes/search/SearchHighlighter.php',
        'SearchIndexField' => __DIR__ . '/includes/search/SearchIndexField.php',
        'SearchIndexFieldDefinition' => __DIR__ . '/includes/search/SearchIndexFieldDefinition.php',
-       'SearchMssql' => __DIR__ . '/includes/search/SearchMssql.php',
        'SearchMySQL' => __DIR__ . '/includes/search/SearchMySQL.php',
        'SearchNearMatchResultSet' => __DIR__ . '/includes/search/SearchNearMatchResultSet.php',
        'SearchNearMatcher' => __DIR__ . '/includes/search/SearchNearMatcher.php',
-       'SearchOracle' => __DIR__ . '/includes/search/SearchOracle.php',
        'SearchPostgres' => __DIR__ . '/includes/search/SearchPostgres.php',
        'SearchResult' => __DIR__ . '/includes/search/SearchResult.php',
        'SearchResultSet' => __DIR__ . '/includes/search/SearchResultSet.php',
index 6a69cd4..a2f6a75 100644 (file)
@@ -61,10 +61,6 @@ class SearchEngineFactory {
                                return SearchMySQL::class;
                        case 'postgres':
                                return SearchPostgres::class;
-                       case 'mssql':
-                               return SearchMssql::class;
-                       case 'oracle':
-                               return SearchOracle::class;
                        default:
                                return SearchEngineDummy::class;
                }
index 2579942..8f0db44 100644 (file)
@@ -74,8 +74,8 @@ class SearchHighlighter {
                        3 => "/(\n\\{\\|)|(\n\\|\\})/" ]; // table
 
                // @todo FIXME: This should prolly be a hook or something
-               // instead of hardcoding a class name from the Cite extension
-               if ( class_exists( 'Cite' ) ) {
+               // instead of hardcoding the name of the Cite extension
+               if ( \ExtensionRegistry::getInstance()->isLoaded( 'Cite' ) ) {
                        $spat .= '|(<ref>)'; // references via cite extension
                        $endPatterns[4] = '/(<ref>)|(<\/ref>)/';
                }
diff --git a/includes/search/SearchMssql.php b/includes/search/SearchMssql.php
deleted file mode 100644 (file)
index 3c0675f..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-<?php
-/**
- * Mssql search engine
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Search
- */
-
-use MediaWiki\MediaWikiServices;
-use Wikimedia\Rdbms\IResultWrapper;
-
-/**
- * Search engine hook base class for Mssql (ConText).
- * @ingroup Search
- */
-class SearchMssql extends SearchDatabase {
-       /**
-        * Perform a full text search query and return a result set.
-        *
-        * @param string $term Raw search term
-        * @return SqlSearchResultSet|null
-        */
-       protected function doSearchTextInDB( $term ) {
-               $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-               $resultSet = $dbr->query( $this->getQuery( $this->filter( $term ), true ) );
-
-               return new SqlSearchResultSet( $resultSet, $this->searchTerms );
-       }
-
-       /**
-        * Perform a title-only search query and return a result set.
-        *
-        * @param string $term Raw search term
-        * @return SqlSearchResultSet|null
-        */
-       protected function doSearchTitleInDB( $term ) {
-               $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-               $resultSet = $dbr->query( $this->getQuery( $this->filter( $term ), false ) );
-
-               return new SqlSearchResultSet( $resultSet, $this->searchTerms );
-       }
-
-       /**
-        * Return a partial WHERE clause to limit the search to the given namespaces
-        *
-        * @return string
-        */
-       private function queryNamespaces() {
-               $namespaces = implode( ',', $this->namespaces );
-               if ( $namespaces == '' ) {
-                       $namespaces = '0';
-               }
-               return 'AND page_namespace IN (' . $namespaces . ')';
-       }
-
-       /**
-        * Return a LIMIT clause to limit results on the query.
-        *
-        * @param string $sql
-        *
-        * @return string
-        */
-       private function queryLimit( $sql ) {
-               $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-
-               return $dbr->limitResult( $sql, $this->limit, $this->offset );
-       }
-
-       /**
-        * Does not do anything for generic search engine
-        * subclasses may define this though
-        *
-        * @param string $filteredTerm
-        * @param bool $fulltext
-        * @return string
-        */
-       function queryRanking( $filteredTerm, $fulltext ) {
-               return ' ORDER BY ftindex.[RANK] DESC'; // return ' ORDER BY score(1)';
-       }
-
-       /**
-        * Construct the full SQL query to do the search.
-        * The guts shoulds be constructed in queryMain()
-        *
-        * @param string $filteredTerm
-        * @param bool $fulltext
-        * @return string
-        */
-       private function getQuery( $filteredTerm, $fulltext ) {
-               return $this->queryLimit( $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
-                       $this->queryNamespaces() . ' ' .
-                       $this->queryRanking( $filteredTerm, $fulltext ) . ' ' );
-       }
-
-       /**
-        * Picks which field to index on, depending on what type of query.
-        *
-        * @param bool $fulltext
-        * @return string
-        */
-       function getIndexField( $fulltext ) {
-               return $fulltext ? 'si_text' : 'si_title';
-       }
-
-       /**
-        * Get the base part of the search query.
-        *
-        * @param string $filteredTerm
-        * @param bool $fulltext
-        * @return string
-        */
-       private function queryMain( $filteredTerm, $fulltext ) {
-               $match = $this->parseQuery( $filteredTerm, $fulltext );
-               $dbr = $this->lb->getMaintenanceConnectionRef( DB_REPLICA );
-               $page = $dbr->tableName( 'page' );
-               $searchindex = $dbr->tableName( 'searchindex' );
-
-               return 'SELECT page_id, page_namespace, page_title, ftindex.[RANK]' .
-                       "FROM $page,FREETEXTTABLE($searchindex , $match, LANGUAGE 'English') as ftindex " .
-                       'WHERE page_id=ftindex.[KEY] ';
-       }
-
-       /** @todo document
-        * @param string $filteredText
-        * @param bool $fulltext
-        * @return string
-        */
-       private function parseQuery( $filteredText, $fulltext ) {
-               $lc = $this->legalSearchChars( self::CHARS_NO_SYNTAX );
-               $this->searchTerms = [];
-
-               # @todo FIXME: This doesn't handle parenthetical expressions.
-               $m = [];
-               $q = [];
-
-               if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
-                       $filteredText, $m, PREG_SET_ORDER ) ) {
-                       foreach ( $m as $terms ) {
-                               $q[] = $terms[1] . MediaWikiServices::getInstance()->getContentLanguage()->
-                                       normalizeForSearch( $terms[2] );
-
-                               if ( !empty( $terms[3] ) ) {
-                                       $regexp = preg_quote( $terms[3], '/' );
-                                       if ( $terms[4] ) {
-                                               $regexp .= "[0-9A-Za-z_]+";
-                                       }
-                               } else {
-                                       $regexp = preg_quote( str_replace( '"', '', $terms[2] ), '/' );
-                               }
-                               $this->searchTerms[] = $regexp;
-                       }
-               }
-
-               $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-               $searchon = $dbr->addQuotes( implode( ',', $q ) );
-               $field = $this->getIndexField( $fulltext );
-
-               return "$field, $searchon";
-       }
-
-       /**
-        * Create or update the search index record for the given page.
-        * Title and text should be pre-processed.
-        *
-        * @param int $id
-        * @param string $title
-        * @param string $text
-        * @return bool|IResultWrapper
-        */
-       function update( $id, $title, $text ) {
-               // We store the column data as UTF-8 byte order marked binary stream
-               // because we are invoking the plain text IFilter on it so that, and we want it
-               // to properly decode the stream as UTF-8.  SQL doesn't support UTF8 as a data type
-               // but the indexer will correctly handle it by this method.  Since all we are doing
-               // is passing this data to the indexer and never retrieving it via PHP, this will save space
-               $dbr = $this->lb->getMaintenanceConnectionRef( DB_MASTER );
-               $table = $dbr->tableName( 'searchindex' );
-               $utf8bom = '0xEFBBBF';
-               $si_title = $utf8bom . bin2hex( $title );
-               $si_text = $utf8bom . bin2hex( $text );
-               $sql = "DELETE FROM $table WHERE si_page = $id;";
-               $sql .= "INSERT INTO $table (si_page, si_title, si_text) VALUES ($id, $si_title, $si_text)";
-               return $dbr->query( $sql, 'SearchMssql::update' );
-       }
-
-       /**
-        * Update a search index record's title only.
-        * Title should be pre-processed.
-        *
-        * @param int $id
-        * @param string $title
-        * @return bool|IResultWrapper
-        */
-       function updateTitle( $id, $title ) {
-               $dbr = $this->lb->getMaintenanceConnectionRef( DB_MASTER );
-               $table = $dbr->tableName( 'searchindex' );
-
-               // see update for why we are using the utf8bom
-               $utf8bom = '0xEFBBBF';
-               $si_title = $utf8bom . bin2hex( $title );
-               $sql = "DELETE FROM $table WHERE si_page = $id;";
-               $sql .= "INSERT INTO $table (si_page, si_title, si_text) VALUES ($id, $si_title, 0x00)";
-               return $dbr->query( $sql, 'SearchMssql::updateTitle' );
-       }
-}
diff --git a/includes/search/SearchOracle.php b/includes/search/SearchOracle.php
deleted file mode 100644 (file)
index d0869bc..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-<?php
-/**
- * Oracle search engine
- *
- * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * https://www.mediawiki.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Search
- */
-
-use MediaWiki\MediaWikiServices;
-
-/**
- * Search engine hook base class for Oracle (ConText).
- * @ingroup Search
- */
-class SearchOracle extends SearchDatabase {
-       private $reservedWords = [
-               'ABOUT' => 1,
-               'ACCUM' => 1,
-               'AND' => 1,
-               'BT' => 1,
-               'BTG' => 1,
-               'BTI' => 1,
-               'BTP' => 1,
-               'FUZZY' => 1,
-               'HASPATH' => 1,
-               'INPATH' => 1,
-               'MINUS' => 1,
-               'NEAR' => 1,
-               'NOT' => 1,
-               'NT' => 1,
-               'NTG' => 1,
-               'NTI' => 1,
-               'NTP' => 1,
-               'OR' => 1,
-               'PT' => 1,
-               'RT' => 1,
-               'SQE' => 1,
-               'SYN' => 1,
-               'TR' => 1,
-               'TRSYN' => 1,
-               'TT' => 1,
-               'WITHIN' => 1,
-       ];
-
-       /**
-        * Perform a full text search query and return a result set.
-        *
-        * @param string $term Raw search term
-        * @return SqlSearchResultSet|null
-        */
-       protected function doSearchTextInDB( $term ) {
-               if ( $term == '' ) {
-                       return null;
-               }
-
-               $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-               $resultSet = $dbr->query( $this->getQuery( $this->filter( $term ), true ) );
-               return new SqlSearchResultSet( $resultSet, $this->searchTerms );
-       }
-
-       /**
-        * Perform a title-only search query and return a result set.
-        *
-        * @param string $term Raw search term
-        * @return SqlSearchResultSet|null
-        */
-       protected function doSearchTitleInDB( $term ) {
-               if ( $term == '' ) {
-                       return null;
-               }
-
-               $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-               $resultSet = $dbr->query( $this->getQuery( $this->filter( $term ), false ) );
-               return new SqlSearchResultSet( $resultSet, $this->searchTerms );
-       }
-
-       /**
-        * Return a partial WHERE clause to limit the search to the given namespaces
-        * @return string
-        */
-       private function queryNamespaces() {
-               if ( is_null( $this->namespaces ) ) {
-                       return '';
-               }
-               if ( $this->namespaces === [] ) {
-                       $namespaces = '0';
-               } else {
-                       $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-                       $namespaces = $dbr->makeList( $this->namespaces );
-               }
-               return 'AND page_namespace IN (' . $namespaces . ')';
-       }
-
-       /**
-        * Return a LIMIT clause to limit results on the query.
-        *
-        * @param string $sql
-        *
-        * @return string
-        */
-       private function queryLimit( $sql ) {
-               $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-
-               return $dbr->limitResult( $sql, $this->limit, $this->offset );
-       }
-
-       /**
-        * Does not do anything for generic search engine
-        * subclasses may define this though
-        *
-        * @param string $filteredTerm
-        * @param bool $fulltext
-        * @return string
-        */
-       function queryRanking( $filteredTerm, $fulltext ) {
-               return ' ORDER BY score(1)';
-       }
-
-       /**
-        * Construct the full SQL query to do the search.
-        * The guts shoulds be constructed in queryMain()
-        * @param string $filteredTerm
-        * @param bool $fulltext
-        * @return string
-        */
-       private function getQuery( $filteredTerm, $fulltext ) {
-               return $this->queryLimit( $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
-                       $this->queryNamespaces() . ' ' .
-                       $this->queryRanking( $filteredTerm, $fulltext ) . ' ' );
-       }
-
-       /**
-        * Picks which field to index on, depending on what type of query.
-        * @param bool $fulltext
-        * @return string
-        */
-       private function getIndexField( $fulltext ) {
-               return $fulltext ? 'si_text' : 'si_title';
-       }
-
-       /**
-        * Get the base part of the search query.
-        *
-        * @param string $filteredTerm
-        * @param bool $fulltext
-        * @return string
-        */
-       function queryMain( $filteredTerm, $fulltext ) {
-               $match = $this->parseQuery( $filteredTerm, $fulltext );
-
-               $dbr = $this->lb->getMaintenanceConnectionRef( DB_REPLICA );
-               $page = $dbr->tableName( 'page' );
-               $searchindex = $dbr->tableName( 'searchindex' );
-
-               return 'SELECT page_id, page_namespace, page_title ' .
-                       "FROM $page,$searchindex " .
-                       'WHERE page_id=si_page AND ' . $match;
-       }
-
-       /**
-        * Parse a user input search string, and return an SQL fragment to be used
-        * as part of a WHERE clause
-        * @param string $filteredText
-        * @param bool $fulltext
-        * @return string
-        */
-       private function parseQuery( $filteredText, $fulltext ) {
-               $lc = $this->legalSearchChars( self::CHARS_NO_SYNTAX );
-               $this->searchTerms = [];
-
-               # @todo FIXME: This doesn't handle parenthetical expressions.
-               $m = [];
-               $searchon = '';
-               if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
-                               $filteredText, $m, PREG_SET_ORDER ) ) {
-                       foreach ( $m as $terms ) {
-                               // Search terms in all variant forms, only
-                               // apply on wiki with LanguageConverter
-                               $temp_terms = MediaWikiServices::getInstance()->getContentLanguage()->
-                                       autoConvertToAllVariants( $terms[2] );
-                               if ( is_array( $temp_terms ) ) {
-                                       $temp_terms = array_unique( array_values( $temp_terms ) );
-                                       foreach ( $temp_terms as $t ) {
-                                               $searchon .= ( $terms[1] == '-' ? ' ~' : ' & ' ) . $this->escapeTerm( $t );
-                                       }
-                               } else {
-                                       $searchon .= ( $terms[1] == '-' ? ' ~' : ' & ' ) . $this->escapeTerm( $terms[2] );
-                               }
-                               if ( !empty( $terms[3] ) ) {
-                                       $regexp = preg_quote( $terms[3], '/' );
-                                       if ( $terms[4] ) {
-                                               $regexp .= "[0-9A-Za-z_]+";
-                                       }
-                               } else {
-                                       $regexp = preg_quote( str_replace( '"', '', $terms[2] ), '/' );
-                               }
-                               $this->searchTerms[] = $regexp;
-                       }
-               }
-
-               $dbr = $this->lb->getConnectionRef( DB_REPLICA );
-               $searchon = $dbr->addQuotes( ltrim( $searchon, ' &' ) );
-               $field = $this->getIndexField( $fulltext );
-
-               return " CONTAINS($field, $searchon, 1) > 0 ";
-       }
-
-       private function escapeTerm( $t ) {
-               $t = MediaWikiServices::getInstance()->getContentLanguage()->normalizeForSearch( $t );
-               $t = isset( $this->reservedWords[strtoupper( $t )] ) ? '{' . $t . '}' : $t;
-               $t = preg_replace( '/^"(.*)"$/', '($1)', $t );
-               $t = preg_replace( '/([-&|])/', '\\\\$1', $t );
-               return $t;
-       }
-
-       /**
-        * Create or update the search index record for the given page.
-        * Title and text should be pre-processed.
-        *
-        * @param int $id
-        * @param string $title
-        * @param string $text
-        */
-       function update( $id, $title, $text ) {
-               $dbw = $this->lb->getMaintenanceConnectionRef( DB_MASTER );
-               $dbw->replace( 'searchindex',
-                       [ 'si_page' ],
-                       [
-                               'si_page' => $id,
-                               'si_title' => $title,
-                               'si_text' => $text
-                       ], 'SearchOracle::update' );
-
-               // Sync the index
-               // We need to specify the DB name (i.e. user/schema) here so that
-               // it can work from the installer, where
-               //     ALTER SESSION SET CURRENT_SCHEMA = ...
-               // was used.
-               $dbw->query( "CALL ctx_ddl.sync_index(" .
-                       $dbw->addQuotes( $dbw->getDBname() . '.' . $dbw->tableName( 'si_text_idx', 'raw' ) ) . ")" );
-               $dbw->query( "CALL ctx_ddl.sync_index(" .
-                       $dbw->addQuotes( $dbw->getDBname() . '.' . $dbw->tableName( 'si_title_idx', 'raw' ) ) . ")" );
-       }
-
-       /**
-        * Update a search index record's title only.
-        * Title should be pre-processed.
-        *
-        * @param int $id
-        * @param string $title
-        */
-       function updateTitle( $id, $title ) {
-               $dbw = $this->lb->getConnectionRef( DB_MASTER );
-               $dbw->update( 'searchindex',
-                       [ 'si_title' => $title ],
-                       [ 'si_page' => $id ],
-                       'SearchOracle::updateTitle',
-                       [] );
-       }
-
-       public function legalSearchChars( $type = self::CHARS_ALL ) {
-               $searchChars = parent::legalSearchChars( $type );
-               if ( $type === self::CHARS_ALL ) {
-                       $searchChars = "\"" . $searchChars;
-               }
-               return $searchChars;
-       }
-}
index bf7a499..5e85bf2 100644 (file)
        "version-db-mariadb-url": "https://mariadb.org/",
        "version-db-percona-url": "http://www.percona.com/software/percona-server",
        "version-db-postgres-url": "http://www.postgresql.org/",
-       "version-db-oracle-url": "http://www.oracle.com/database/",
        "version-db-sqlite-url": "https://www.sqlite.org/",
-       "version-db-mssql-url": "https://www.microsoft.com/sql/",
        "version-entrypoints": "Entry point URLs",
        "version-entrypoints-header-entrypoint": "Entry point",
        "version-entrypoints-header-url": "URL",
index 9e53809..21b7cc7 100644 (file)
        "version-db-mariadb-url": "{{ignored}}URL to the website of MariaDB",
        "version-db-percona-url": "{{ignored}}URL to the website of Percona",
        "version-db-postgres-url": "{{ignored}}URL to the website of PostgreSQL",
-       "version-db-oracle-url": "{{ignored}}URL to the website of Oracle",
        "version-db-sqlite-url": "{{ignored}}URL to the website of SQLite",
-       "version-db-mssql-url": "{{ignored}}URL to the website of Microsoft SQL Server",
        "version-entrypoints": "Header on [[Special:Version]] above a table that lists the URLs of various entry points in this MediaWiki installation. Entry points are the \"places\" where the wiki's content and information can be accessed in various ways, for instance the standard index.php which shows normal pages, histories etc.",
        "version-entrypoints-header-entrypoint": "Header for the first column in the entry points table on [[Special:Version]].\nSee also {{msg-mw|Version-entrypoints}}",
        "version-entrypoints-header-url": "Header for the second column in the entry points table on [[Special:Version]].\n{{Identical|URL}}",
index 773bd51..ca2e99f 100644 (file)
@@ -24,9 +24,7 @@ class TestUser {
 
        private function assertNotReal() {
                global $wgDBprefix;
-               if ( $wgDBprefix !== MediaWikiTestCase::DB_PREFIX &&
-                       $wgDBprefix !== MediaWikiTestCase::ORA_DB_PREFIX
-               ) {
+               if ( $wgDBprefix !== MediaWikiTestCase::DB_PREFIX ) {
                        throw new MWException( "Can't create user on real database" );
                }
        }