Merge "You are reviewing an old revision should be a warningbox"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 26 Sep 2019 19:41:48 +0000 (19:41 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 26 Sep 2019 19:41:48 +0000 (19:41 +0000)
22 files changed:
includes/CommentStore.php
includes/MediaWiki.php
includes/Revision/RevisionStore.php
includes/api/ApiQueryBacklinksprop.php
includes/api/ApiQueryBase.php
includes/exception/BadRequestError.php
includes/exception/ErrorPageError.php
includes/exception/PermissionsError.php
includes/exception/ThrottledError.php
includes/exception/UserNotLoggedIn.php
includes/filerepo/file/LocalFileLockError.php
includes/parser/Parser.php
languages/i18n/ban.json
languages/i18n/exif/nap.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/it.json
languages/i18n/lv.json
languages/i18n/nap.json
languages/i18n/te.json
tests/phpunit/includes/CommentStoreTest.php
tests/phpunit/includes/Revision/RevisionStoreDbTestBase.php

index 994a064..9054e7a 100644 (file)
@@ -83,7 +83,8 @@ class CommentStore {
        protected $key = null;
 
        /**
-        * @var int One of the MIGRATION_* constants
+        * @var int One of the MIGRATION_* constants, or an appropriate combination
+        *  of SCHEMA_COMPAT_* constants.
         * @todo Deprecate and remove once extensions seem unlikely to need to use
         *  it for migration anymore.
         */
@@ -98,11 +99,19 @@ class CommentStore {
        /**
         * @param Language $lang Language to use for comment truncation. Defaults
         *  to content language.
-        * @param int $migrationStage One of the MIGRATION_* constants. Always
-        *  MIGRATION_NEW for MediaWiki core since 1.33.
+        * @param int $stage One of the MIGRATION_* constants, or an appropriate
+        *  combination of SCHEMA_COMPAT_* constants. Always MIGRATION_NEW for
+        *  MediaWiki core since 1.33.
         */
-       public function __construct( Language $lang, $migrationStage ) {
-               $this->stage = $migrationStage;
+       public function __construct( Language $lang, $stage ) {
+               if ( ( $stage & SCHEMA_COMPAT_WRITE_BOTH ) === 0 ) {
+                       throw new InvalidArgumentException( '$stage must include a write mode' );
+               }
+               if ( ( $stage & SCHEMA_COMPAT_READ_BOTH ) === 0 ) {
+                       throw new InvalidArgumentException( '$stage must include a read mode' );
+               }
+
+               $this->stage = $stage;
                $this->lang = $lang;
        }
 
@@ -166,21 +175,21 @@ class CommentStore {
        public function getFields( $key = null ) {
                $key = $this->getKey( $key );
                $fields = [];
-               if ( $this->stage === MIGRATION_OLD ) {
+               if ( ( $this->stage & SCHEMA_COMPAT_READ_BOTH ) === SCHEMA_COMPAT_READ_OLD ) {
                        $fields["{$key}_text"] = $key;
                        $fields["{$key}_data"] = 'NULL';
                        $fields["{$key}_cid"] = 'NULL';
-               } else {
-                       if ( $this->stage < MIGRATION_NEW ) {
+               } else { // READ_BOTH or READ_NEW
+                       if ( $this->stage & SCHEMA_COMPAT_READ_OLD ) {
                                $fields["{$key}_old"] = $key;
                        }
 
                        $tempTableStage = isset( $this->tempTables[$key] )
                                ? $this->tempTables[$key]['stage'] : MIGRATION_NEW;
-                       if ( $tempTableStage < MIGRATION_NEW ) {
+                       if ( $tempTableStage & SCHEMA_COMPAT_READ_OLD ) {
                                $fields["{$key}_pk"] = $this->tempTables[$key]['joinPK'];
                        }
-                       if ( $tempTableStage > MIGRATION_OLD ) {
+                       if ( $tempTableStage & SCHEMA_COMPAT_READ_NEW ) {
                                $fields["{$key}_id"] = "{$key}_id";
                        }
                }
@@ -211,21 +220,21 @@ class CommentStore {
                        $fields = [];
                        $joins = [];
 
-                       if ( $this->stage === MIGRATION_OLD ) {
+                       if ( ( $this->stage & SCHEMA_COMPAT_READ_BOTH ) === SCHEMA_COMPAT_READ_OLD ) {
                                $fields["{$key}_text"] = $key;
                                $fields["{$key}_data"] = 'NULL';
                                $fields["{$key}_cid"] = 'NULL';
-                       } else {
-                               $join = $this->stage === MIGRATION_NEW ? 'JOIN' : 'LEFT JOIN';
+                       } else { // READ_BOTH or READ_NEW
+                               $join = ( $this->stage & SCHEMA_COMPAT_READ_OLD ) ? 'LEFT JOIN' : 'JOIN';
 
                                $tempTableStage = isset( $this->tempTables[$key] )
                                        ? $this->tempTables[$key]['stage'] : MIGRATION_NEW;
-                               if ( $tempTableStage < MIGRATION_NEW ) {
+                               if ( $tempTableStage & SCHEMA_COMPAT_READ_OLD ) {
                                        $t = $this->tempTables[$key];
                                        $alias = "temp_$key";
                                        $tables[$alias] = $t['table'];
                                        $joins[$alias] = [ $join, "{$alias}.{$t['pk']} = {$t['joinPK']}" ];
-                                       if ( $tempTableStage === MIGRATION_OLD ) {
+                                       if ( ( $tempTableStage & SCHEMA_COMPAT_READ_BOTH ) === SCHEMA_COMPAT_READ_OLD ) {
                                                $joinField = "{$alias}.{$t['field']}";
                                        } else {
                                                // Nothing hits this code path for now, but will in the future when we set
@@ -245,7 +254,7 @@ class CommentStore {
                                $tables[$alias] = 'comment';
                                $joins[$alias] = [ $join, "{$alias}.comment_id = {$joinField}" ];
 
-                               if ( $this->stage === MIGRATION_NEW ) {
+                               if ( ( $this->stage & SCHEMA_COMPAT_READ_BOTH ) === SCHEMA_COMPAT_READ_NEW ) {
                                        $fields["{$key}_text"] = "{$alias}.comment_text";
                                } else {
                                        $fields["{$key}_text"] = "COALESCE( {$alias}.comment_text, $key )";
@@ -282,13 +291,15 @@ class CommentStore {
                        $cid = $row["{$key}_cid"] ?? null;
                        $text = $row["{$key}_text"];
                        $data = $row["{$key}_data"];
-               } elseif ( $this->stage === MIGRATION_OLD ) {
+               } elseif ( ( $this->stage & SCHEMA_COMPAT_READ_BOTH ) === SCHEMA_COMPAT_READ_OLD ) {
                        $cid = null;
                        if ( $fallback && isset( $row[$key] ) ) {
                                wfLogWarning( "Using deprecated fallback handling for comment $key" );
                                $text = $row[$key];
                        } else {
-                               wfLogWarning( "Missing {$key}_text and {$key}_data fields in row with MIGRATION_OLD" );
+                               wfLogWarning(
+                                       "Missing {$key}_text and {$key}_data fields in row with MIGRATION_OLD / READ_OLD"
+                               );
                                $text = '';
                        }
                        $data = null;
@@ -296,7 +307,7 @@ class CommentStore {
                        $tempTableStage = isset( $this->tempTables[$key] )
                                ? $this->tempTables[$key]['stage'] : MIGRATION_NEW;
                        $row2 = null;
-                       if ( $tempTableStage > MIGRATION_OLD && array_key_exists( "{$key}_id", $row ) ) {
+                       if ( ( $tempTableStage & SCHEMA_COMPAT_READ_NEW ) && array_key_exists( "{$key}_id", $row ) ) {
                                if ( !$db ) {
                                        throw new InvalidArgumentException(
                                                "\$row does not contain fields needed for comment $key and getComment(), but "
@@ -311,7 +322,9 @@ class CommentStore {
                                        __METHOD__
                                );
                        }
-                       if ( !$row2 && $tempTableStage < MIGRATION_NEW && array_key_exists( "{$key}_pk", $row ) ) {
+                       if ( !$row2 && ( $tempTableStage & SCHEMA_COMPAT_READ_OLD ) &&
+                               array_key_exists( "{$key}_pk", $row )
+                       ) {
                                if ( !$db ) {
                                        throw new InvalidArgumentException(
                                                "\$row does not contain fields needed for comment $key and getComment(), but "
@@ -341,7 +354,9 @@ class CommentStore {
                                $cid = $row2->comment_id;
                                $text = $row2->comment_text;
                                $data = $row2->comment_data;
-                       } elseif ( $this->stage < MIGRATION_NEW && array_key_exists( "{$key}_old", $row ) ) {
+                       } elseif ( ( $this->stage & SCHEMA_COMPAT_READ_OLD ) &&
+                               array_key_exists( "{$key}_old", $row )
+                       ) {
                                $cid = null;
                                $text = $row["{$key}_old"];
                                $data = null;
@@ -474,7 +489,7 @@ class CommentStore {
                # Truncate comment in a Unicode-sensitive manner
                $comment->text = $this->lang->truncateForVisual( $comment->text, self::COMMENT_CHARACTER_LIMIT );
 
-               if ( $this->stage > MIGRATION_OLD && !$comment->id ) {
+               if ( ( $this->stage & SCHEMA_COMPAT_WRITE_NEW ) && !$comment->id ) {
                        $dbData = $comment->data;
                        if ( !$comment->message instanceof RawMessage ) {
                                if ( $dbData === null ) {
@@ -534,14 +549,14 @@ class CommentStore {
 
                $comment = $this->createComment( $dbw, $comment, $data );
 
-               if ( $this->stage <= MIGRATION_WRITE_BOTH ) {
+               if ( $this->stage & SCHEMA_COMPAT_WRITE_OLD ) {
                        $fields[$key] = $this->lang->truncateForDatabase( $comment->text, 255 );
                }
 
-               if ( $this->stage >= MIGRATION_WRITE_BOTH ) {
+               if ( $this->stage & SCHEMA_COMPAT_WRITE_NEW ) {
                        $tempTableStage = isset( $this->tempTables[$key] )
                                ? $this->tempTables[$key]['stage'] : MIGRATION_NEW;
-                       if ( $tempTableStage <= MIGRATION_WRITE_BOTH ) {
+                       if ( $tempTableStage & SCHEMA_COMPAT_WRITE_OLD ) {
                                $t = $this->tempTables[$key];
                                $func = __METHOD__;
                                $commentId = $comment->id;
@@ -556,7 +571,7 @@ class CommentStore {
                                        );
                                };
                        }
-                       if ( $tempTableStage >= MIGRATION_WRITE_BOTH ) {
+                       if ( $tempTableStage & SCHEMA_COMPAT_WRITE_NEW ) {
                                $fields["{$key}_id"] = $comment->id;
                        }
                }
@@ -594,7 +609,7 @@ class CommentStore {
 
                $tempTableStage = isset( $this->tempTables[$key] )
                        ? $this->tempTables[$key]['stage'] : MIGRATION_NEW;
-               if ( $tempTableStage < MIGRATION_WRITE_NEW ) {
+               if ( $tempTableStage & SCHEMA_COMPAT_WRITE_OLD ) {
                        throw new InvalidArgumentException( "Must use insertWithTempTable() for $key" );
                }
 
index 28c9e16..1a75714 100644 (file)
@@ -526,11 +526,15 @@ class MediaWiki {
                        try {
                                $this->main();
                        } catch ( ErrorPageError $e ) {
+                               $out = $this->context->getOutput();
+                               // TODO: Should ErrorPageError::report accept a OutputPage parameter?
+                               $e->report( ErrorPageError::STAGE_OUTPUT );
+
                                // T64091: while exceptions are convenient to bubble up GUI errors,
                                // they are not internal application faults. As with normal requests, this
                                // should commit, print the output, do deferred updates, jobs, and profiling.
                                $this->doPreOutputCommit();
-                               $e->report(); // display the GUI error
+                               $out->output(); // display the GUI error
                        }
                } catch ( Exception $e ) {
                        $context = $this->context;
index a5cf840..a1aeccb 100644 (file)
@@ -1928,7 +1928,10 @@ class RevisionStore
                $titlesByPageId = [];
                foreach ( $rows as $row ) {
                        if ( isset( $rowsByRevId[$row->rev_id] ) ) {
-                               throw new InvalidArgumentException( "Duplicate rows in newRevisionsFromBatch {$row->rev_id}" );
+                               $result->warning(
+                                       'internalerror',
+                                       "Duplicate rows in newRevisionsFromBatch, rev_id {$row->rev_id}"
+                               );
                        }
                        if ( $title && $row->rev_page != $title->getArticleID() ) {
                                throw new InvalidArgumentException(
index b8672ee..022fd9b 100644 (file)
@@ -286,6 +286,8 @@ class ApiQueryBacklinksprop extends ApiQueryGeneratorBase {
                $res = $this->select( __METHOD__ );
 
                if ( is_null( $resultPageSet ) ) {
+                       $this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
+
                        $count = 0;
                        foreach ( $res as $row ) {
                                if ( ++$count > $params['limit'] ) {
index 8d9cb48..059c438 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  */
 
+use MediaWiki\MediaWikiServices;
 use Wikimedia\Rdbms\IDatabase;
 use Wikimedia\Rdbms\IResultWrapper;
 
@@ -569,6 +570,42 @@ abstract class ApiQueryBase extends ApiBase {
                );
        }
 
+       /**
+        * Preprocess the result set to fill the GenderCache with the necessary information
+        * before using self::addTitleInfo
+        *
+        * @param IResultWrapper $res Result set to work on.
+        *  The result set must have _namespace and _title fields with the provided field prefix
+        * @param string $fname The caller function name, always use __METHOD__
+        * @param string $fieldPrefix Prefix for fields to check gender for
+        */
+       protected function executeGenderCacheFromResultWrapper(
+               IResultWrapper $res, $fname = __METHOD__, $fieldPrefix = 'page'
+       ) {
+               if ( !$res->numRows() ) {
+                       return;
+               }
+
+               $services = MediaWikiServices::getInstance();
+               $nsInfo = $services->getNamespaceInfo();
+               $namespaceField = $fieldPrefix . '_namespace';
+               $titleField = $fieldPrefix . '_title';
+
+               $usernames = [];
+               foreach ( $res as $row ) {
+                       if ( $nsInfo->hasGenderDistinction( $row->$namespaceField ) ) {
+                               $usernames[] = $row->$titleField;
+                       }
+               }
+
+               if ( $usernames === [] ) {
+                       return;
+               }
+
+               $genderCache = $services->getGenderCache();
+               $genderCache->doQuery( $usernames, $fname );
+       }
+
        /** @} */
 
        /************************************************************************//**
index 5fcf0e6..2448421 100644 (file)
@@ -26,9 +26,9 @@
  */
 class BadRequestError extends ErrorPageError {
 
-       public function report() {
+       public function report( $action = self::SEND_OUTPUT ) {
                global $wgOut;
                $wgOut->setStatusCode( 400 );
-               parent::report();
+               parent::report( $action );
        }
 }
index 4b18126..64216a4 100644 (file)
@@ -25,6 +25,8 @@
  * @ingroup Exception
  */
 class ErrorPageError extends MWException implements ILocalizedException {
+       const SEND_OUTPUT = 0;
+       const STAGE_OUTPUT = 1;
        public $title, $msg, $params;
 
        /**
@@ -60,13 +62,19 @@ class ErrorPageError extends MWException implements ILocalizedException {
                return wfMessage( $this->msg, $this->params );
        }
 
-       public function report() {
+       public function report( $action = self::SEND_OUTPUT ) {
                if ( self::isCommandLine() || defined( 'MW_API' ) ) {
                        parent::report();
                } else {
                        global $wgOut;
                        $wgOut->showErrorPage( $this->title, $this->msg, $this->params );
-                       $wgOut->output();
+                       // Allow skipping of the final output step, so that web-based page views
+                       // from MediaWiki.php, can inspect the staged OutputPage state, and perform
+                       // graceful shutdown via doPreOutputCommit first, just like for regular
+                       // output when there isn't an error page.
+                       if ( $action === self::SEND_OUTPUT ) {
+                               $wgOut->output();
+                       }
                }
        }
 }
index 87a3dc2..9fa1c7c 100644 (file)
@@ -67,10 +67,12 @@ class PermissionsError extends ErrorPageError {
                parent::__construct( 'permissionserrors', Message::newFromSpecifier( $errors[0] ) );
        }
 
-       public function report() {
+       public function report( $action = self::SEND_OUTPUT ) {
                global $wgOut;
 
                $wgOut->showPermissionsErrorPage( $this->errors, $this->permission );
-               $wgOut->output();
+               if ( $action === self::SEND_OUTPUT ) {
+                       $wgOut->output();
+               }
        }
 }
index bec0d90..cdeb402 100644 (file)
@@ -32,9 +32,9 @@ class ThrottledError extends ErrorPageError {
                );
        }
 
-       public function report() {
+       public function report( $action = ErrorPageError::SEND_OUTPUT ) {
                global $wgOut;
                $wgOut->setStatusCode( 429 );
-               parent::report();
+               parent::report( $action );
        }
 }
index 246c944..ff992b0 100644 (file)
@@ -75,11 +75,11 @@ class UserNotLoggedIn extends ErrorPageError {
         * Redirect to Special:Userlogin if the specified message is compatible. Otherwise,
         * show an error page as usual.
         */
-       public function report() {
+       public function report( $action = self::SEND_OUTPUT ) {
                // If an unsupported message is used, don't try redirecting to Special:Userlogin,
                // since the message may not be compatible.
                if ( !in_array( $this->msg, LoginHelper::getValidErrorMessages() ) ) {
-                       parent::report();
+                       parent::report( $action );
                        return;
                }
 
@@ -99,6 +99,8 @@ class UserNotLoggedIn extends ErrorPageError {
                        'warning' => $this->msg,
                ] ) );
 
-               $output->output();
+               if ( $action === self::SEND_OUTPUT ) {
+                       $output->output();
+               }
        }
 }
index 7cfc8c2..b76f3da 100644 (file)
@@ -29,9 +29,9 @@ class LocalFileLockError extends ErrorPageError {
                );
        }
 
-       public function report() {
+       public function report( $action = self::SEND_OUTPUT ) {
                global $wgOut;
                $wgOut->setStatusCode( 429 );
-               parent::report();
+               parent::report( $action );
        }
 }
index ec1628f..9ec5834 100644 (file)
@@ -910,7 +910,7 @@ class Parser {
         */
        public function setTitle( $t ) {
                if ( !$t ) {
-                       $t = Title::newFromText( 'NO TITLE' );
+                       $t = Title::makeTitle( NS_SPECIAL, 'Badtitle/Parser' );
                }
 
                if ( $t->hasFragment() ) {
index e834be3..d4ab79e 100644 (file)
        "tog-numberheadings": "isinin nomor murda anggen cara otomatis",
        "tog-editondblclick": "sunting lembar nganggen klik kaping pindo",
        "tog-editsectiononrightclick": "sayagayang panyuntingan kepahan anggen ngeklik tengen ring kepahan judul",
-       "tog-watchcreations": "imbuhin lembar sane karyanin titiang ring kepahan pangiwasan",
+       "tog-watchcreations": "Tambeh kaca sané kardi titiang miwah berkas sané unggah titiang ring pangawasan titiang",
        "tog-watchdefault": "imbuhin lembar panyuntingansane sunting titiang ring kepahan pangiwasan",
-       "tog-watchmoves": "imbuhang lembar sane kakisidang titiang ring kepahan pangiwasan",
+       "tog-watchmoves": "Tambeh kaca miwan berkas sané gingsirang titiang ring pangawasan titiang",
        "tog-watchdeletion": "imbuhin lembar sane kaapus ring kepahan pangiwasan",
-       "tog-watchuploads": "Tambehin berkas anyar sané unggah tiang ka pupulan pantaun\nTambahkan berkas baru yang saya unggah ke daftar pantauan",
+       "tog-watchuploads": "Tambeh berkas anyar sané unggah titiang ring pangawasan titiang",
        "tog-watchrollback": "Tambehin kaca sané sampun uliang tiang ka tengah pupulan pantauan tiangé",
        "tog-minordefault": "pingetin samian suntingan dados suntingan alit sane ajeg",
        "tog-previewontop": "tampilang pratayang sadurung kotak sunting lan nenten sadurungnyane",
index 76bd5e0..3326a75 100644 (file)
@@ -3,7 +3,8 @@
                "authors": [
                        "C.R.",
                        "E. abu Filumena",
-                       "SabineCretella"
+                       "SabineCretella",
+                       "Sannita"
                ]
        },
        "exif-imagewidth": "Larghezza",
        "exif-imagedescription": "Titulo 'e l'immaggene",
        "exif-make": "Frabbeca ca muntaje 'a camera",
        "exif-model": "Mudello d' 'a camera",
-       "exif-software": "Software ausàto",
+       "exif-software": "Software ausato",
        "exif-artist": "Autore",
        "exif-copyright": "Titolare d' 'o Copyright",
-       "exif-exifversion": "Verzione d'Exif",
+       "exif-exifversion": "Verzione 'e ll'exif",
        "exif-flashpixversion": "Verziona Flashpix suppurtata",
        "exif-colorspace": "Spazio d' 'e culore",
        "exif-componentsconfiguration": "Significato d'ogne componente",
index 7d8e596..20d2991 100644 (file)
        "version-specialpages": "Toimintosivut",
        "version-parserhooks": "Jäsenninkytkökset",
        "version-variables": "Muuttujat",
-       "version-editors": "Muokkaajat",
+       "version-editors": "Muokkaimet",
        "version-antispam": "Roskalinkkien estäminen",
        "version-other": "Muut",
        "version-mediahandlers": "Median käsittelijät",
index 07f248d..53d54a2 100644 (file)
        "thursday": "jeudi",
        "friday": "vendredi",
        "saturday": "samedi",
-       "sun": "Dim.",
-       "mon": "Lun.",
-       "tue": "Mar.",
-       "wed": "Mer.",
-       "thu": "Jeu.",
-       "fri": "Ven.",
-       "sat": "Sam.",
+       "sun": "dim.",
+       "mon": "lun.",
+       "tue": "mar.",
+       "wed": "mer.",
+       "thu": "jeu.",
+       "fri": "ven.",
+       "sat": "sam.",
        "january": "janvier",
        "february": "février",
        "march": "mars",
index a75adf5..50ef092 100644 (file)
        "ipblocklist-legend": "Cerca un utente bloccato",
        "blocklist-userblocks": "Nascondi i blocchi degli utenti registrati",
        "blocklist-tempblocks": "Nascondi i blocchi temporanei",
+       "blocklist-indefblocks": "Nascondi blocchi infiniti",
        "blocklist-addressblocks": "Nascondi i blocchi di un solo IP",
        "blocklist-type": "Tipo:",
        "blocklist-type-opt-all": "Tutto",
index f355e60..8d79167 100644 (file)
        "password-login-forbidden": "Šī lietotājvārda un paroles izmantošana ir aizliegta.",
        "mailmypassword": "Atiestatīt paroli",
        "passwordremindertitle": "Jauna pagaidu parole no {{SITENAME}}s",
-       "passwordremindertext": "Kāds (iespējams, Tu pats, no IP adreses $1)\nlūdza, lai nosūtām Tev jaunu {{SITENAME}} ($4) paroli.\nLietotajam $2 pagaidu parole tagad ir $3.\nLudzu, nomaini paroli, kad esi veiksmīgi iekļuvis iekšš.\nTavas pagaidu paroles derīguma termiņš beigsies pēc {{PLURAL:$5|$5 dienām|$5 dienas|$5 dienām}}.\n\nJa paroles pieprasījumu bija nosūtījis kāds cits, vai arī tu atcerējies savu veco paroli, šo var ignorēt. Vecā parole joprojām darbojas.",
+       "passwordremindertext": "Kāds (no IP adreses $1)\nlūdza, lai nosūtām tev jaunu {{SITENAME}} ($4) paroli.\nLietotajam $2 izveidota pagaidu parole $3. Ja tāds bija tavs mērķis, tagad tev jāpieslēdzas un jānomaina parole. Tavas pagaidu paroles derīguma termiņš beigsies pēc {{PLURAL:$5|$5 dienām|$5 dienas|$5 dienām}}.\n\nJa paroles pieprasījumu bija nosūtījis kāds cits, vai arī tu atcerējies savu veco paroli, šo var ignorēt. Vecā parole joprojām darbojas.",
        "noemail": "Lietotājs \"$1\" nav reģistrējis e-pasta adresi.",
        "noemailcreate": "Tev jānorāda derīgu e-pasta adresi",
        "passwordsent": "Esam nosūtījuši jaunu paroli uz e-pasta adresi, kuru ir norādījis lietotājs $1. Lūdzu, nāc iekšā ar jauno paroli, kad būsi to saņēmis.",
index e421252..14235e1 100644 (file)
        "protect": "Prutegge",
        "protect_change": "càgna",
        "unprotect": "Càgna prutezzione",
-       "newpage": "Paggena nòva",
+       "newpage": "Paggena nova",
        "talkpagelinktext": "Chiàcchiera",
        "specialpage": "Paggena speciàle",
        "personaltools": "Strumiente perzonale",
        "shown-title": "Fa verè {{PLURAL:$1|nu risultato|$1 risultate}} pe paggena",
        "viewprevnext": "Vire ($1 {{int:pipe-separator}} $2) ($3).",
        "searchmenu-exists": "'''Ncopp' 'o sito esiste na paggena c' 'o nomme \"[[:$1]]\"'''\n{{PLURAL:$2|0=|Vedite pure dint'a l'ati risultate 'e cerca.}}",
-       "searchmenu-new": "<strong>'''Crèa 'a paggena \"[[:$1]]\" ncopp'a stu wiki!'''</strong> {{PLURAL:$2|0=|Vedite pure 'a paggena truvata c' 'a recerca vuosta|Vedite pure 'e risultate d\"a recerca}}",
+       "searchmenu-new": "<strong>'''Crèa 'a paggena \"[[:$1]]\" ncopp'a sta wiki!'''</strong> {{PLURAL:$2|0=|Vedite pure 'a paggena truvata c' 'a recerca vuosta|Vedite pure 'e risultate d' 'a recerca}}",
        "searchprofile-articles": "Paggene 'e contenute",
        "searchprofile-images": "Multimedia",
        "searchprofile-everything": "Tutto",
        "right-suppressionlog": "Vide 'e riggistre private",
        "right-block": "Nun fa fa' cagnamienti a ll'at'utente",
        "right-blockemail": "Nun fa mannà e-mail a n'utente",
-       "right-hideuser": "Blocca n'utente e fallo sparì 'a 'o pubbreco",
+       "right-hideuser": "Fremma n'utente e annascunnillo r'o pubbreco",
        "right-ipblock-exempt": "Ignora 'e blocche 'e l'IP, 'e blocche automatece e li blocche 'e range 'e l'IP",
        "right-unblockself": "Sblocca se stesso",
        "right-protect": "Cagna 'e livelle 'e prutezione 'e cagna paggene prutette ricurzivamente",
        "right-mergehistory": "Aunisce 'a cronologgia d' 'e paggene",
        "right-userrights": "Cagna 'e deritte 'e ll'utente",
        "right-userrights-interwiki": "Cagna 'e deritte 'e ll'utente int'a l'ati wiki",
-       "right-siteadmin": "Blocca e sblocca 'o database",
+       "right-siteadmin": "Chiure e arape 'o database",
        "right-override-export-depth": "Esporta 'e paggene azzeccanno 'e paggene cullegate nfin'a na profondità 'e 5",
        "right-sendemail": "Manna na mail a ll'at'utente",
        "right-managechangetags": "Crìa e appiccia/stuta 'e [[Special:Tags|tag]]",
        "uploadlogpage": "Riggistro 'e carreche",
        "uploadlogpagetext": "Ccà abbascio song'alencate l'urdeme file carrecate.\nCuntrullate 'a [[Special:NewFiles|gallaria d' 'e file nuove]] pe' ve ffà na guardata cchiù visuale 'e tutto.",
        "filename": "Nomme d' 'o file",
-       "filedesc": "Énnece",
+       "filedesc": "Riepilego",
        "fileuploadsummary": "Dettaglie:",
        "filereuploadsummary": "Cagnamiente a 'o file:",
        "filestatus": "Stato d' 'o copyright:",
index d3e4af9..83a72df 100644 (file)
@@ -64,6 +64,7 @@
        "tog-watchlisthideminor": "చిన్న మార్పులను నా వీక్షణా జాబితాలో చూపించొద్దు",
        "tog-watchlisthideliu": "లాగిన్ ఐన వాడుకరులు చేసే మార్పులను వీక్షణా జాబితాలో చూపించకు",
        "tog-watchlistreloadautomatically": "ఫిల్టరు మారినప్పుడెల్లా వీక్షణ జాబితాను తిరిగి లోడు చెయ్యి (JavaScript అవసరం)",
+       "tog-watchlistunwatchlinks": "మార్పులు జరిగిన వీక్షణ పేజీలకు నేరుగా వీక్షించు/వద్దు సూచికలను ({{int:Watchlist-unwatch}}/{{int:Watchlist-unwatch-undo}}) చేర్చు (టాగుల్ చెయాలంటే JavaScript ఆవశ్యకం)",
        "tog-watchlisthideanons": "అజ్ఞాత వాడుకరుల మార్పులను వీక్షణా జాబితాలో చూపించకు",
        "tog-watchlisthidepatrolled": "నిఘా ఉన్న మార్పులను వీక్షణజాబితా నుంచి దాచిపెట్టు",
        "tog-watchlisthidecategorization": "పేజీ వర్గీకరణను దాచు",
@@ -74,6 +75,7 @@
        "tog-useeditwarning": "ఏదైనా పేజీని నేను వదిలివెళ్తున్నప్పుడు దానిలో భద్రపరచని మార్పులు ఉంటే నన్ను హెచ్చరించు",
        "tog-prefershttps": "లాగిన్ అయి ఉన్నప్పుడెల్లా భద్ర కనెక్షనునే వాడు",
        "tog-showrollbackconfirmation": "రోల్‌బ్యాక్ లింకును నొక్కినపుడు నిర్ధారించుకునే సందేశాన్ని చూపించు",
+       "tog-requireemail": "సంకేతపదం మార్చుకోడానికి ఈమెయిలు ఆవశ్యకం",
        "underline-always": "ఎల్లప్పుడూ",
        "underline-never": "ఎప్పటికీ వద్దు",
        "underline-default": "అలంకారపు లేదా విహారిణి అప్రమేయం",
        "createaccountmail": "ఏదో ఒక తాత్కాలిక సంకేతపదాన్ని వాడి దాన్ని పేర్కొన్న ఈమెయిలు చిరునామాకు పంపించు",
        "createaccountmail-help": "సంకేతపదం తెలుసుకోనవసరం లేకుండా వేరొకరి కోసం ఖాతా సృష్టించేందుకు వాడవచ్చు.",
        "createacct-realname": "అసలు పేరు (ఐచ్చికం)",
-       "createacct-reason": "కారణం",
+       "createacct-reason": "కారణం (అందరికీ కనిపిస్తుంది)",
        "createacct-reason-ph": "మీరు మరో ఖాతాను ఎందుకు సృష్టించుకుంటున్నారు",
        "createacct-reason-help": "సృష్టించిన ఖాతాల చిట్టాలో చూపించే సందేశం",
        "createacct-submit": "మీ ఖాతాను సృష్టించుకోండి",
        "botpasswords": "బాట్ సంకేతపదాలు",
        "botpasswords-disabled": "బాట్ సంకేతపదాలను అచేతనం చేసాం.",
        "botpasswords-no-central-id": "బాఅత్ సంకేతపదాలను వాడాలంటే, మీరు ఒక కేంద్రీకృత ఖాతాలోకి లాగినవ్వాలి.",
+       "botpasswords-existing": "ప్రస్తుతం ఉన్న బాట్ సంకేతపదాలు",
        "botpasswords-createnew": "ఓ కొత్త బాట్ సంకేతపదాన్ని సృష్టించండి",
        "botpasswords-editexisting": "ఉనికిలో ఉన్న బాట్ సంకేతపదాన్ని మార్చండి",
+       "botpasswords-label-needsreset": "(సంకేతపదాన్ని మార్చాల్సిన అవసరం ఉంది)",
        "botpasswords-label-appid": "బాట్ పేరు:",
        "botpasswords-label-create": "సృష్టించు",
        "botpasswords-label-update": "తాజాకరించు",
index 9c08b9f..57cc073 100644 (file)
@@ -73,6 +73,47 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                return $store;
        }
 
+       /**
+        * @dataProvider provideConstructor
+        * @param int $stage
+        * @param string|null $exceptionMsg
+        */
+       public function testConstructor( $stage, $exceptionMsg ) {
+               try {
+                       $m = new CommentStore( Language::factory( 'qqx' ), $stage );
+                       if ( $exceptionMsg !== null ) {
+                               $this->fail( 'Expected exception not thrown' );
+                       }
+                       $this->assertInstanceOf( CommentStore::class, $m );
+               } catch ( InvalidArgumentException $ex ) {
+                       $this->assertSame( $exceptionMsg, $ex->getMessage() );
+               }
+       }
+
+       public static function provideConstructor() {
+               return [
+                       [ 0, '$stage must include a write mode' ],
+                       [ SCHEMA_COMPAT_READ_OLD, '$stage must include a write mode' ],
+                       [ SCHEMA_COMPAT_READ_NEW, '$stage must include a write mode' ],
+                       [ SCHEMA_COMPAT_READ_BOTH, '$stage must include a write mode' ],
+
+                       [ SCHEMA_COMPAT_WRITE_OLD, '$stage must include a read mode' ],
+                       [ SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_OLD, null ],
+                       [ SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_NEW, null ],
+                       [ SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_BOTH, null ],
+
+                       [ SCHEMA_COMPAT_WRITE_NEW, '$stage must include a read mode' ],
+                       [ SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_OLD, null ],
+                       [ SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_NEW, null ],
+                       [ SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_BOTH, null ],
+
+                       [ SCHEMA_COMPAT_WRITE_BOTH, '$stage must include a read mode' ],
+                       [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, null ],
+                       [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, null ],
+                       [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_BOTH, null ],
+               ];
+       }
+
        /**
         * @dataProvider provideGetFields
         * @param int $stage
@@ -115,6 +156,14 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                MIGRATION_NEW, 'ipb_reason',
                                [ 'ipb_reason_id' => 'ipb_reason_id' ],
                        ],
+                       'Simple table, write-both/read-old' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'ipb_reason',
+                               [ 'ipb_reason_text' => 'ipb_reason', 'ipb_reason_data' => 'NULL', 'ipb_reason_cid' => 'NULL' ],
+                       ],
+                       'Simple table, write-both/read-new' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'ipb_reason',
+                               [ 'ipb_reason_id' => 'ipb_reason_id' ],
+                       ],
 
                        'Revision, old' => [
                                MIGRATION_OLD, 'rev_comment',
@@ -136,6 +185,18 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                MIGRATION_NEW, 'rev_comment',
                                [ 'rev_comment_pk' => 'rev_id' ],
                        ],
+                       'Revision, write-both/read-old' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'rev_comment',
+                               [
+                                       'rev_comment_text' => 'rev_comment',
+                                       'rev_comment_data' => 'NULL',
+                                       'rev_comment_cid' => 'NULL',
+                               ],
+                       ],
+                       'Revision, write-both/read-new' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'rev_comment',
+                               [ 'rev_comment_pk' => 'rev_id' ],
+                       ],
 
                        'Image, old' => [
                                MIGRATION_OLD, 'img_description',
@@ -165,6 +226,20 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                        'img_description_id' => 'img_description_id'
                                ],
                        ],
+                       'Image, write-both/read-old' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'img_description',
+                               [
+                                       'img_description_text' => 'img_description',
+                                       'img_description_data' => 'NULL',
+                                       'img_description_cid' => 'NULL',
+                               ],
+                       ],
+                       'Image, write-both/read-new' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'img_description',
+                               [
+                                       'img_description_id' => 'img_description_id'
+                               ],
+                       ],
                ];
        }
 
@@ -244,6 +319,30 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                        ],
                                ],
                        ],
+                       'Simple table, write-both/read-old' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'ipb_reason', [
+                                       'tables' => [],
+                                       'fields' => [
+                                               'ipb_reason_text' => 'ipb_reason',
+                                               'ipb_reason_data' => 'NULL',
+                                               'ipb_reason_cid' => 'NULL',
+                                       ],
+                                       'joins' => [],
+                               ],
+                       ],
+                       'Simple table, write-both/read-new' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'ipb_reason', [
+                                       'tables' => [ 'comment_ipb_reason' => 'comment' ],
+                                       'fields' => [
+                                               'ipb_reason_text' => 'comment_ipb_reason.comment_text',
+                                               'ipb_reason_data' => 'comment_ipb_reason.comment_data',
+                                               'ipb_reason_cid' => 'comment_ipb_reason.comment_id',
+                                       ],
+                                       'joins' => [
+                                               'comment_ipb_reason' => [ 'JOIN', 'comment_ipb_reason.comment_id = ipb_reason_id' ],
+                                       ],
+                               ],
+                       ],
 
                        'Revision, old' => [
                                MIGRATION_OLD, 'rev_comment', [
@@ -310,6 +409,35 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                        ],
                                ],
                        ],
+                       'Revision, write-both/read-old' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'rev_comment', [
+                                       'tables' => [],
+                                       'fields' => [
+                                               'rev_comment_text' => 'rev_comment',
+                                               'rev_comment_data' => 'NULL',
+                                               'rev_comment_cid' => 'NULL',
+                                       ],
+                                       'joins' => [],
+                               ],
+                       ],
+                       'Revision, write-both/read-new' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'rev_comment', [
+                                       'tables' => [
+                                               'temp_rev_comment' => 'revision_comment_temp',
+                                               'comment_rev_comment' => 'comment',
+                                       ],
+                                       'fields' => [
+                                               'rev_comment_text' => 'comment_rev_comment.comment_text',
+                                               'rev_comment_data' => 'comment_rev_comment.comment_data',
+                                               'rev_comment_cid' => 'comment_rev_comment.comment_id',
+                                       ],
+                                       'joins' => [
+                                               'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
+                                               'comment_rev_comment' => [ 'JOIN',
+                                                       'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       ],
+                               ],
+                       ],
 
                        'Image, old' => [
                                MIGRATION_OLD, 'img_description', [
@@ -373,6 +501,34 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                        ],
                                ],
                        ],
+                       'Image, write-both/read-old' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'img_description', [
+                                       'tables' => [],
+                                       'fields' => [
+                                               'img_description_text' => 'img_description',
+                                               'img_description_data' => 'NULL',
+                                               'img_description_cid' => 'NULL',
+                                       ],
+                                       'joins' => [],
+                               ],
+                       ],
+                       'Image, write-both/read-new' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'img_description', [
+                                       'tables' => [
+                                               'comment_img_description' => 'comment',
+                                       ],
+                                       'fields' => [
+                                               'img_description_text' => 'comment_img_description.comment_text',
+                                               'img_description_data' => 'comment_img_description.comment_data',
+                                               'img_description_cid' => 'comment_img_description.comment_id',
+                                       ],
+                                       'joins' => [
+                                               'comment_img_description' => [ 'JOIN',
+                                                       'comment_img_description.comment_id = img_description_id',
+                                               ],
+                                       ],
+                               ],
+                       ],
                ];
        }
 
@@ -413,6 +569,15 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                MIGRATION_NEW ],
                        MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
                        MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
+
+                       SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD => [
+                               MIGRATION_OLD, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, MIGRATION_NEW
+                       ],
+                       SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW => [
+                               MIGRATION_OLD, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, MIGRATION_NEW
+                       ],
                ];
 
                foreach ( $stages as $writeStage => $possibleReadStages ) {
@@ -427,12 +592,12 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                $fields = $wstore->insert( $this->db, $key, $comment, $data );
                        }
 
-                       if ( $writeStage <= MIGRATION_WRITE_BOTH ) {
+                       if ( $writeStage & SCHEMA_COMPAT_WRITE_OLD ) {
                                $this->assertSame( $expect['text'], $fields[$key], "old field, stage=$writeStage" );
                        } else {
                                $this->assertArrayNotHasKey( $key, $fields, "old field, stage=$writeStage" );
                        }
-                       if ( $writeStage >= MIGRATION_WRITE_BOTH && !$usesTemp ) {
+                       if ( ( $writeStage & SCHEMA_COMPAT_WRITE_NEW ) && !$usesTemp ) {
                                $this->assertArrayHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
                        } else {
                                $this->assertArrayNotHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
@@ -463,13 +628,17 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                        $queryInfo['joins']
                                );
 
+                               $expectForCombination = (
+                                       ( $writeStage & SCHEMA_COMPAT_WRITE_BOTH ) === SCHEMA_COMPAT_WRITE_OLD ||
+                                       ( $readStage & SCHEMA_COMPAT_READ_BOTH ) === SCHEMA_COMPAT_READ_OLD
+                               ) ? $expectOld : $expect;
                                $this->assertComment(
-                                       $writeStage === MIGRATION_OLD || $readStage === MIGRATION_OLD ? $expectOld : $expect,
+                                       $expectForCombination,
                                        $rstore->getCommentLegacy( $this->db, $key, $fieldRow ),
                                        "w=$writeStage, r=$readStage, from getFields()"
                                );
                                $this->assertComment(
-                                       $writeStage === MIGRATION_OLD || $readStage === MIGRATION_OLD ? $expectOld : $expect,
+                                       $expectForCombination,
                                        $rstore->getComment( $key, $joinRow ),
                                        "w=$writeStage, r=$readStage, from getJoin()"
                                );
@@ -503,6 +672,15 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                MIGRATION_NEW ],
                        MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
                        MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
+
+                       SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD => [
+                               MIGRATION_OLD, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, MIGRATION_NEW
+                       ],
+                       SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW => [
+                               MIGRATION_OLD, SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, MIGRATION_NEW
+                       ],
                ];
 
                foreach ( $stages as $writeStage => $possibleReadStages ) {
@@ -517,12 +695,12 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                $fields = $wstore->insert( $this->db, $comment, $data );
                        }
 
-                       if ( $writeStage <= MIGRATION_WRITE_BOTH ) {
+                       if ( $writeStage & SCHEMA_COMPAT_WRITE_OLD ) {
                                $this->assertSame( $expect['text'], $fields[$key], "old field, stage=$writeStage" );
                        } else {
                                $this->assertArrayNotHasKey( $key, $fields, "old field, stage=$writeStage" );
                        }
-                       if ( $writeStage >= MIGRATION_WRITE_BOTH && !$usesTemp ) {
+                       if ( ( $writeStage & SCHEMA_COMPAT_WRITE_NEW ) && !$usesTemp ) {
                                $this->assertArrayHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
                        } else {
                                $this->assertArrayNotHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
@@ -553,13 +731,17 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                                        $queryInfo['joins']
                                );
 
+                               $expectForCombination = (
+                                       ( $writeStage & SCHEMA_COMPAT_WRITE_BOTH ) === SCHEMA_COMPAT_WRITE_OLD ||
+                                       ( $readStage & SCHEMA_COMPAT_READ_BOTH ) === SCHEMA_COMPAT_READ_OLD
+                               ) ? $expectOld : $expect;
                                $this->assertComment(
-                                       $writeStage === MIGRATION_OLD || $readStage === MIGRATION_OLD ? $expectOld : $expect,
+                                       $expectForCombination,
                                        $rstore->getCommentLegacy( $this->db, $fieldRow ),
                                        "w=$writeStage, r=$readStage, from getFields()"
                                );
                                $this->assertComment(
-                                       $writeStage === MIGRATION_OLD || $readStage === MIGRATION_OLD ? $expectOld : $expect,
+                                       $expectForCombination,
                                        $rstore->getComment( $joinRow ),
                                        "w=$writeStage, r=$readStage, from getJoin()"
                                );
@@ -725,6 +907,9 @@ class CommentStoreTest extends MediaWikiLangTestCase {
                        'MIGRATION_WRITE_BOTH' => [ MIGRATION_WRITE_BOTH ],
                        'MIGRATION_WRITE_NEW' => [ MIGRATION_WRITE_NEW ],
                        'MIGRATION_NEW' => [ MIGRATION_NEW ],
+
+                       'SCHEMA_COMPAT write-both/read-old' => [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD ],
+                       'SCHEMA_COMPAT write-both/read-new' => [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW ],
                ];
        }
 
index 4040ffc..6bf219d 100644 (file)
@@ -2076,8 +2076,10 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase {
                /** @var Revision $rev1 */
                $rev1 = $editStatus->getValue()['revision'];
 
-               $this->setExpectedException( InvalidArgumentException::class );
-               MediaWikiServices::getInstance()->getRevisionStore()
+               $status = MediaWikiServices::getInstance()->getRevisionStore()
                        ->newRevisionsFromBatch( [ $this->revisionToRow( $rev1 ), $this->revisionToRow( $rev1 ) ] );
+
+               $this->assertFalse( $status->isGood() );
+               $this->assertTrue( $status->hasMessage( 'internalerror' ) );
        }
 }