Merge "Prevent "Undefined offset notice""
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 29 Jun 2018 19:34:47 +0000 (19:34 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 29 Jun 2018 19:34:47 +0000 (19:34 +0000)
19 files changed:
RELEASE-NOTES-1.32
includes/MWNamespace.php
includes/MediaWikiServices.php
includes/MovePage.php
includes/ServiceWiring.php
includes/Storage/PageUpdater.php
includes/Storage/RevisionStore.php
includes/Storage/RevisionStoreFactory.php [new file with mode: 0644]
includes/deferred/LinksUpdate.php
includes/page/WikiPage.php
languages/data/Names.php
languages/messages/MessagesMni.php [new file with mode: 0644]
languages/messages/MessagesSa.php
maintenance/updateCollation.php
resources/src/mediawiki.special.changeslist.css
tests/phpunit/includes/MWNamespaceTest.php
tests/phpunit/includes/MediaWikiServicesTest.php
tests/phpunit/includes/Storage/RevisionStoreFactoryTest.php [new file with mode: 0644]
tests/phpunit/includes/page/WikiPageDbTestBase.php

index 36ec3d3..d0d5eb2 100644 (file)
@@ -97,6 +97,7 @@ because of Phabricator reports.
 * (T194047) Added language support for Shawiya, Latin script (shy-latn).
 * (T195940) Added language support for Batak Mandailing (btm).
 * (T137491) Added language support for Standard Moroccan Amazigh (zgh).
+* (T198132) Added language support for Manipuri (mni).
 
 === Breaking changes in 1.32 ===
 * $wgRequestTime, deprecated in 1.25, was removed. Use
index 73fdd82..1df5d51 100644 (file)
@@ -540,4 +540,26 @@ class MWNamespace {
 
                return $usableLevels;
        }
+
+       /**
+        * Returns the link type to be used for categories.
+        *
+        * This determines which section of a category page titles
+        * in the namespace will appear within.
+        *
+        * @since 1.32
+        * @param int $index Namespace index
+        * @return string One of 'subcat', 'file', 'page'
+        */
+       public static function getCategoryLinkType( $index ) {
+               self::isMethodValidFor( $index, __METHOD__ );
+
+               if ( $index == NS_CATEGORY ) {
+                       return 'subcat';
+               } elseif ( $index == NS_FILE ) {
+                       return 'file';
+               } else {
+                       return 'page';
+               }
+       }
 }
index ac15574..caaa6b3 100644 (file)
@@ -21,6 +21,9 @@ use MediaWiki\Storage\NameTableStore;
 use MediaWiki\Storage\RevisionFactory;
 use MediaWiki\Storage\RevisionLookup;
 use MediaWiki\Storage\RevisionStore;
+use MediaWiki\Storage\RevisionStoreFactory;
+use OldRevisionImporter;
+use UploadRevisionImporter;
 use Wikimedia\Rdbms\LBFactory;
 use LinkCache;
 use Wikimedia\Rdbms\LoadBalancer;
@@ -757,6 +760,14 @@ class MediaWikiServices extends ServiceContainer {
                return $this->getService( 'RevisionStore' );
        }
 
+       /**
+        * @since 1.32
+        * @return RevisionStoreFactory
+        */
+       public function getRevisionStoreFactory() {
+               return $this->getService( 'RevisionStoreFactory' );
+       }
+
        /**
         * @since 1.31
         * @return RevisionLookup
@@ -829,6 +840,22 @@ class MediaWikiServices extends ServiceContainer {
                return $this->getService( 'ActorMigration' );
        }
 
+       /**
+        * @since 1.32
+        * @return UploadRevisionImporter
+        */
+       public function getUploadRevisionImporter() {
+               return $this->getService( 'UploadRevisionImporter' );
+       }
+
+       /**
+        * @since 1.32
+        * @return OldRevisionImporter
+        */
+       public function getOldRevisionImporter() {
+               return $this->getService( 'OldRevisionImporter' );
+       }
+
        ///////////////////////////////////////////////////////////////////////////
        // NOTE: When adding a service getter here, don't forget to add a test
        // case for it in MediaWikiServicesTest::provideGetters() and in
index 614ea7d..ec44b6e 100644 (file)
@@ -280,13 +280,7 @@ class MovePage {
                        [ 'cl_from' => $pageid ],
                        __METHOD__
                );
-               if ( $this->newTitle->getNamespace() == NS_CATEGORY ) {
-                       $type = 'subcat';
-               } elseif ( $this->newTitle->getNamespace() == NS_FILE ) {
-                       $type = 'file';
-               } else {
-                       $type = 'page';
-               }
+               $type = MWNamespace::getCategoryLinkType( $this->newTitle->getNamespace() );
                foreach ( $prefixes as $prefixRow ) {
                        $prefix = $prefixRow->cl_sortkey_prefix;
                        $catTo = $prefixRow->cl_to;
index 425b789..ba576d5 100644 (file)
@@ -46,7 +46,7 @@ use MediaWiki\Preferences\DefaultPreferencesFactory;
 use MediaWiki\Shell\CommandFactory;
 use MediaWiki\Storage\BlobStoreFactory;
 use MediaWiki\Storage\NameTableStore;
-use MediaWiki\Storage\RevisionStore;
+use MediaWiki\Storage\RevisionStoreFactory;
 use MediaWiki\Storage\SqlBlobStore;
 use Wikimedia\ObjectFactory;
 
@@ -463,10 +463,15 @@ return [
        },
 
        'RevisionStore' => function ( MediaWikiServices $services ) {
+               return $services->getRevisionStoreFactory()->getRevisionStore();
+       },
+
+       'RevisionStoreFactory' => function ( MediaWikiServices $services ) {
                /** @var SqlBlobStore $blobStore */
                $blobStore = $services->getService( '_SqlBlobStore' );
+               $config = $services->getMainConfig();
 
-               $store = new RevisionStore(
+               $store = new RevisionStoreFactory(
                        $services->getDBLoadBalancer(),
                        $blobStore,
                        $services->getMainWANObjectCache(),
@@ -474,14 +479,11 @@ return [
                        $services->getContentModelStore(),
                        $services->getSlotRoleStore(),
                        $services->getMainConfig()->get( 'MultiContentRevisionSchemaMigrationStage' ),
-                       $services->getActorMigration()
+                       $services->getActorMigration(),
+                       LoggerFactory::getInstance( 'RevisionStore' ),
+                       $config->get( 'ContentHandlerUseDB' )
                );
 
-               $store->setLogger( LoggerFactory::getInstance( 'RevisionStore' ) );
-
-               $config = $services->getMainConfig();
-               $store->setContentHandlerUseDB( $config->get( 'ContentHandlerUseDB' ) );
-
                return $store;
        },
 
index 7900210..2376d16 100644 (file)
@@ -45,6 +45,7 @@ use User;
 use Wikimedia\Assert\Assert;
 use Wikimedia\Rdbms\DBConnRef;
 use Wikimedia\Rdbms\DBUnexpectedError;
+use Wikimedia\Rdbms\IDatabase;
 use Wikimedia\Rdbms\LoadBalancer;
 use WikiPage;
 
@@ -639,7 +640,7 @@ class PageUpdater {
                // NOTE: This grabs the parent revision as the CAS token, if grabParentRevision
                // wasn't called yet. If the page is modified by another process before we are done with
                // it, this method must fail (with status 'edit-conflict')!
-               // NOTE: The parent revision may be different from $this->baseRevisionId.
+               // NOTE: The parent revision may be different from $this->originalRevisionId.
                $this->grabParentRevision();
                $flags = $this->checkFlags( $flags );
 
@@ -922,7 +923,6 @@ class PageUpdater {
 
                // XXX: we may want a flag that allows a null revision to be forced!
                $changed = $this->derivedDataUpdater->isChange();
-               $mainContent = $newRevisionRecord->getContent( 'main' );
 
                $dbw = $this->getDBConnectionRef( DB_MASTER );
 
@@ -991,22 +991,19 @@ class PageUpdater {
                        $user->incEditCount();
 
                        $dbw->endAtomic( __METHOD__ );
-               } else {
-                       // T34948: revision ID must be set to page {{REVISIONID}} and
-                       // related variables correctly. Likewise for {{REVISIONUSER}} (T135261).
-                       // Since we don't insert a new revision into the database, the least
-                       // error-prone way is to reuse given old revision.
-                       $newRevisionRecord = $oldRev;
-                       $newLegacyRevision = new Revision( $newRevisionRecord );
-               }
 
-               if ( $changed ) {
                        // Return the new revision to the caller
                        $status->value['revision-record'] = $newRevisionRecord;
 
                        // TODO: globally replace usages of 'revision' with getNewRevision()
                        $status->value['revision'] = $newLegacyRevision;
                } else {
+                       // T34948: revision ID must be set to page {{REVISIONID}} and
+                       // related variables correctly. Likewise for {{REVISIONUSER}} (T135261).
+                       // Since we don't insert a new revision into the database, the least
+                       // error-prone way is to reuse given old revision.
+                       $newRevisionRecord = $oldRev;
+
                        $status->warning( 'edit-no-change' );
                        // Update page_touched as updateRevisionOn() was not called.
                        // Other cache updates are managed in WikiPage::onArticleEdit()
@@ -1021,30 +1018,15 @@ class PageUpdater {
                // importantly, before the parser cache has been updated. This would cause the
                // content to be parsed a second time, or may cause stale content to be shown.
                DeferredUpdates::addUpdate(
-                       new AtomicSectionUpdate(
+                       $this->getAtomicSectionUpdate(
                                $dbw,
-                               __METHOD__,
-                               function () use (
-                                       $wikiPage, $newRevisionRecord, $newLegacyRevision, $user, $mainContent,
-                                       $summary, $flags, $changed, $status
-                               ) {
-                                       // Update links tables, site stats, etc.
-                                       $this->derivedDataUpdater->prepareUpdate(
-                                               $newRevisionRecord,
-                                               [
-                                                       'changed' => $changed,
-                                               ]
-                                       );
-                                       $this->derivedDataUpdater->doUpdates();
-
-                                       // Trigger post-save hook
-                                       // TODO: replace legacy hook!
-                                       // TODO: avoid pass-by-reference, see T193950
-                                       $params = [ &$wikiPage, &$user, $mainContent, $summary->text, $flags & EDIT_MINOR,
-                                               null, null, &$flags, $newLegacyRevision, &$status, $this->getOriginalRevisionId(),
-                                               $this->undidRevId ];
-                                       Hooks::run( 'PageContentSaveComplete', $params );
-                               }
+                               $wikiPage,
+                               $newRevisionRecord,
+                               $user,
+                               $summary,
+                               $flags,
+                               $status,
+                               [ 'changed' => $changed, ]
                        ),
                        DeferredUpdates::PRESEND
                );
@@ -1162,47 +1144,65 @@ class PageUpdater {
                $status->value['revision'] = $newLegacyRevision;
                $status->value['revision-record'] = $newRevisionRecord;
 
-               // XXX: make sure we are not loading the Content from the DB
-               $mainContent = $newRevisionRecord->getContent( 'main' );
-
                // Do secondary updates once the main changes have been committed...
                DeferredUpdates::addUpdate(
-                       new AtomicSectionUpdate(
+                       $this->getAtomicSectionUpdate(
                                $dbw,
-                               __METHOD__,
-                               function () use (
-                                       $wikiPage,
-                                       $newRevisionRecord,
-                                       $newLegacyRevision,
-                                       $user,
-                                       $mainContent,
-                                       $summary,
-                                       $flags,
-                                       $status
-                               ) {
-                                       // Update links, etc.
-                                       $this->derivedDataUpdater->prepareUpdate(
-                                               $newRevisionRecord,
-                                               [ 'created' => true ]
-                                       );
-                                       $this->derivedDataUpdater->doUpdates();
+                               $wikiPage,
+                               $newRevisionRecord,
+                               $user,
+                               $summary,
+                               $flags,
+                               $status,
+                               [ 'created' => true ]
+                       ),
+                       DeferredUpdates::PRESEND
+               );
 
+               return $status;
+       }
+
+       private function getAtomicSectionUpdate(
+               IDatabase $dbw,
+               WikiPage $wikiPage,
+               RevisionRecord $newRevisionRecord,
+               User $user,
+               CommentStoreComment $summary,
+               $flags,
+               Status $status,
+               $hints = []
+       ) {
+               return new AtomicSectionUpdate(
+                       $dbw,
+                       __METHOD__,
+                       function () use (
+                               $wikiPage, $newRevisionRecord, $user,
+                               $summary, $flags, $status, $hints
+                       ) {
+                               $newLegacyRevision = new Revision( $newRevisionRecord );
+                               $mainContent = $newRevisionRecord->getContent( 'main', RevisionRecord::RAW );
+
+                               // Update links tables, site stats, etc.
+                               $this->derivedDataUpdater->prepareUpdate( $newRevisionRecord, $hints );
+                               $this->derivedDataUpdater->doUpdates();
+
+                               // TODO: replace legacy hook!
+                               // TODO: avoid pass-by-reference, see T193950
+
+                               if ( $hints['created'] ?? false ) {
                                        // Trigger post-create hook
-                                       // TODO: replace legacy hook!
-                                       // TODO: avoid pass-by-reference, see T193950
                                        $params = [ &$wikiPage, &$user, $mainContent, $summary->text,
                                                $flags & EDIT_MINOR, null, null, &$flags, $newLegacyRevision ];
                                        Hooks::run( 'PageContentInsertComplete', $params );
-                                       // Trigger post-save hook
-                                       // TODO: replace legacy hook!
-                                       $params = array_merge( $params, [ &$status, $this->getOriginalRevisionId(), 0 ] );
-                                       Hooks::run( 'PageContentSaveComplete', $params );
                                }
-                       ),
-                       DeferredUpdates::PRESEND
-               );
 
-               return $status;
+                               // Trigger post-save hook
+                               $params = [ &$wikiPage, &$user, $mainContent, $summary->text,
+                                               $flags & EDIT_MINOR, null, null, &$flags, $newLegacyRevision,
+                                               &$status, $this->getOriginalRevisionId(), $this->undidRevId ];
+                               Hooks::run( 'PageContentSaveComplete', $params );
+                       }
+               );
        }
 
 }
index 6c30d62..12bee1e 100644 (file)
@@ -83,6 +83,7 @@ class RevisionStore
 
        /**
         * @var boolean
+        * @see $wgContentHandlerUseDB
         */
        private $contentHandlerUseDB = true;
 
@@ -182,6 +183,7 @@ class RevisionStore
        }
 
        /**
+        * @see $wgContentHandlerUseDB
         * @param bool $contentHandlerUseDB
         * @throws MWException
         */
diff --git a/includes/Storage/RevisionStoreFactory.php b/includes/Storage/RevisionStoreFactory.php
new file mode 100644 (file)
index 0000000..6f8bd99
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+
+/**
+ * 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
+ *
+ * Attribution notice: when this file was created, much of its content was taken
+ * from the Revision.php file as present in release 1.30. Refer to the history
+ * of that file for original authorship.
+ *
+ * @file
+ */
+
+namespace MediaWiki\Storage;
+
+use ActorMigration;
+use CommentStore;
+use Psr\Log\LoggerInterface;
+use WANObjectCache;
+use Wikimedia\Assert\Assert;
+use Wikimedia\Rdbms\LoadBalancer;
+
+/**
+ * @since 1.32
+ */
+class RevisionStoreFactory {
+
+       /** @var SqlBlobStore */
+       private $blobStore;
+
+       /** @var LoadBalancer */
+       private $loadBalancer;
+
+       /** @var WANObjectCache */
+       private $cache;
+
+       /** @var CommentStore */
+       private $commentStore;
+
+       /** @var ActorMigration */
+       private $actorMigration;
+
+       /** @var NameTableStore */
+       private $contentModelStore;
+
+       /** @var NameTableStore */
+       private $slotRoleStore;
+
+       /** @var int One of the MIGRATION_* constants */
+       private $mcrMigrationStage;
+
+       /**
+        * @var bool
+        * @see $wgContentHandlerUseDB
+        */
+       private $contentHandlerUseDB;
+
+       /** @var LoggerInterface */
+       private $logger;
+
+       /**
+        * @todo $blobStore should be allowed to be any BlobStore!
+        *
+        * @param LoadBalancer $loadBalancer
+        * @param SqlBlobStore $blobStore
+        * @param WANObjectCache $cache
+        * @param CommentStore $commentStore
+        * @param NameTableStore $contentModelStore
+        * @param NameTableStore $slotRoleStore
+        * @param int $migrationStage
+        * @param ActorMigration $actorMigration
+        * @param LoggerInterface $logger
+        * @param bool $contentHandlerUseDB see {@link $wgContentHandlerUseDB}
+        */
+       public function __construct(
+               LoadBalancer $loadBalancer,
+               SqlBlobStore $blobStore,
+               WANObjectCache $cache,
+               CommentStore $commentStore,
+               NameTableStore $contentModelStore,
+               NameTableStore $slotRoleStore,
+               $migrationStage,
+               ActorMigration $actorMigration,
+               LoggerInterface $logger,
+               $contentHandlerUseDB
+       ) {
+               Assert::parameterType( 'integer', $migrationStage, '$migrationStage' );
+
+               $this->loadBalancer = $loadBalancer;
+               $this->blobStore = $blobStore;
+               $this->cache = $cache;
+               $this->commentStore = $commentStore;
+               $this->contentModelStore = $contentModelStore;
+               $this->slotRoleStore = $slotRoleStore;
+               $this->mcrMigrationStage = $migrationStage;
+               $this->actorMigration = $actorMigration;
+               $this->logger = $logger;
+               $this->contentHandlerUseDB = $contentHandlerUseDB;
+       }
+
+       /**
+        * @since 1.32
+        *
+        * @param bool|string $wikiId false for the current domain / wikid
+        *
+        * @return RevisionStore for the given wikiId with all necessary services and a logger
+        */
+       public function getRevisionStore( $wikiId = false ) {
+               Assert::parameterType( 'string|boolean', $wikiId, '$wikiId' );
+
+               $store = new RevisionStore(
+                       $this->loadBalancer,
+                       $this->blobStore,
+                       $this->cache,
+                       $this->commentStore,
+                       $this->contentModelStore,
+                       $this->slotRoleStore,
+                       $this->mcrMigrationStage,
+                       $this->actorMigration,
+                       $wikiId
+               );
+
+               $store->setLogger( $this->logger );
+               $store->setContentHandlerUseDB( $this->contentHandlerUseDB );
+
+               return $store;
+       }
+
+}
index 398df01..5c82f09 100644 (file)
@@ -593,13 +593,7 @@ class LinksUpdate extends DataUpdate implements EnqueueableDataUpdate {
                        $nt = Title::makeTitleSafe( NS_CATEGORY, $name );
                        $wgContLang->findVariantLink( $name, $nt, true );
 
-                       if ( $this->mTitle->getNamespace() == NS_CATEGORY ) {
-                               $type = 'subcat';
-                       } elseif ( $this->mTitle->getNamespace() == NS_FILE ) {
-                               $type = 'file';
-                       } else {
-                               $type = 'page';
-                       }
+                       $type = MWNamespace::getCategoryLinkType( $this->mTitle->getNamespace() );
 
                        # Treat custom sortkeys as a prefix, so that if multiple
                        # things are forced to sort as '*' or something, they'll
index 18ecff4..ad3c8c5 100644 (file)
@@ -2962,6 +2962,13 @@ class WikiPage implements Page, IDBAccessObject {
                $updater->setUndidRevisionId( $current->getId() );
                $updater->addTags( $tags );
 
+               // TODO: this logic should not be in the storage layer, it's here for compatibility
+               // with 1.31 behavior. Applying the 'autopatrol' right should be done in the same
+               // place the 'bot' right is handled, which is currently in EditPage::attemptSave.
+               if ( $wgUseRCPatrol && $this->getTitle()->userCan( 'autopatrol', $guser ) ) {
+                       $updater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED );
+               }
+
                // Actually store the rollback
                $rev = $updater->saveRevision(
                        CommentStoreComment::newUnsavedComment( $summary ),
@@ -3251,16 +3258,13 @@ class WikiPage implements Page, IDBAccessObject {
         */
        public function updateCategoryCounts( array $added, array $deleted, $id = 0 ) {
                $id = $id ?: $this->getId();
-               $ns = $this->getTitle()->getNamespace();
+               $type = MWNamespace::getCategoryLinkType( $this->getTitle()->getNamespace() );
 
                $addFields = [ 'cat_pages = cat_pages + 1' ];
                $removeFields = [ 'cat_pages = cat_pages - 1' ];
-               if ( $ns == NS_CATEGORY ) {
-                       $addFields[] = 'cat_subcats = cat_subcats + 1';
-                       $removeFields[] = 'cat_subcats = cat_subcats - 1';
-               } elseif ( $ns == NS_FILE ) {
-                       $addFields[] = 'cat_files = cat_files + 1';
-                       $removeFields[] = 'cat_files = cat_files - 1';
+               if ( $type !== 'page' ) {
+                       $addFields[] = "cat_{$type}s = cat_{$type}s + 1";
+                       $removeFields[] = "cat_{$type}s = cat_{$type}s - 1";
                }
 
                $dbw = wfGetDB( DB_MASTER );
@@ -3292,8 +3296,8 @@ class WikiPage implements Page, IDBAccessObject {
                                        $insertRows[] = [
                                                'cat_title'   => $cat,
                                                'cat_pages'   => 1,
-                                               'cat_subcats' => ( $ns == NS_CATEGORY ) ? 1 : 0,
-                                               'cat_files'   => ( $ns == NS_FILE ) ? 1 : 0,
+                                               'cat_subcats' => ( $type === 'subcat' ) ? 1 : 0,
+                                               'cat_files'   => ( $type === 'file' ) ? 1 : 0,
                                        ];
                                }
                                $dbw->upsert(
index 97ff012..277bd02 100644 (file)
@@ -297,6 +297,7 @@ class Names {
                'mk' => 'македонски', # Macedonian
                'ml' => 'മലയാളം', # Malayalam
                'mn' => 'монгол', # Halh Mongolian (Cyrillic) (ISO 639-3: khk)
+               'mni' => 'মেইতেই লোন্', # Manipuri/Meitei
                'mo' => 'молдовеняскэ', # Moldovan, deprecated
                'mr' => 'मराठी', # Marathi
                'mrj' => 'кырык мары', # Hill Mari
diff --git a/languages/messages/MessagesMni.php b/languages/messages/MessagesMni.php
new file mode 100644 (file)
index 0000000..1641c2a
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+/** Manipuri/Meitei (মেইতেই লোন্)
+ *
+ * To improve a translation please visit https://translatewiki.net
+ *
+ * @ingroup Language
+ * @file
+ *
+ */
index aa5fdeb..81a8a14 100644 (file)
@@ -92,92 +92,92 @@ $namespaceAliases = [
 ];
 
 $specialPageAliases = [
-       'Allmessages'               => [ 'सर्वप्रणाली-संदेश' ],
-       'Allpages'                  => [ 'सर्वपृष्टानि' ],
-       'Ancientpages'              => [ 'पूर्वतनपृष्टानि' ],
-       'Blankpage'                 => [ 'रिक्तपृष्ठ' ],
-       'Block'                     => [ 'सदस्यप्रतिबन्ध' ],
-       'Booksources'               => [ 'पुस्तकस्रोत' ],
-       'BrokenRedirects'           => [ 'खण्डीतपुनर्निर्देशन' ],
-       'Categories'                => [ 'वर्गः' ],
-       'ChangePassword'            => [ 'सङ्केतशब्दपुन:प्रयुक्ता' ],
-       'Confirmemail'              => [ 'विपत्रपुष्टिकृते' ],
-       'Contributions'             => [ 'योगदानम्' ],
-       'CreateAccount'             => [ 'सृज्उपयोजकसंज्ञा' ],
-       'Deadendpages'              => [ 'निराग्रपृष्टानि' ],
-       'DeletedContributions'      => [ 'परित्यागितयोगदान' ],
-       'DoubleRedirects'           => [ 'पुनर्निर्देशनद्वंद्व' ],
-       'Emailuser'                 => [ 'विपत्रयोजक' ],
-       'ExpandTemplates'           => [ 'बिंबधरविस्तारकरोसि' ],
-       'Export'                    => [ 'निर्यात' ],
-       'Fewestrevisions'           => [ 'स्वल्पपरिवर्तन' ],
-       'FileDuplicateSearch'       => [ 'अनुकृतसंचिकाशोध' ],
-       'Filepath'                  => [ 'संचिकापथ' ],
-       'Import'                    => [ 'आयात' ],
-       'Invalidateemail'           => [ 'अमान्यविपत्र' ],
-       'BlockList'                 => [ 'प्रतिबन्धसूची' ],
-       'LinkSearch'                => [ 'सम्बन्धन्‌शोध' ],
-       'Listadmins'                => [ 'प्रचालकसूची' ],
-       'Listbots'                  => [ 'स्वयंअनुकृसूची' ],
-       'Listfiles'                 => [ 'चित्रसूची', 'संचिकासूचि' ],
-       'Listgrouprights'           => [ 'गटअधिकारसूची' ],
-       'Listredirects'             => [ 'विचालन्‌सूची' ],
-       'Listusers'                 => [ 'सदस्यासूची' ],
-       'Lockdb'                    => [ 'विदाद्वारंबन्ध्' ],
-       'Log'                       => [ 'अङ्कन' ],
-       'Lonelypages'               => [ 'अकलपृष्टानि' ],
-       'Longpages'                 => [ 'दीर्घपृष्टानि' ],
-       'MergeHistory'              => [ 'इतिहाससंयोग' ],
-       'MIMEsearch'                => [ 'विविधामाप_(माईम)_शोधसि' ],
-       'Mostcategories'            => [ 'अधिकतमवर्ग' ],
-       'Mostimages'                => [ 'अधिकतमसम्भन्दिन्_संचिका' ],
-       'Mostlinked'                => [ 'अधिकतमसम्भन्दिन्_पृष्टानि', 'अधिकतमसम्भन्दिन्' ],
-       'Mostlinkedcategories'      => [ 'अधिकतमसम्भन्दिन्_वर्ग' ],
-       'Mostlinkedtemplates'       => [ 'अधिकतमसम्भन्दिन्_फलकानि' ],
-       'Mostrevisions'             => [ 'अधिकतमपरिवर्तन' ],
-       'Movepage'                  => [ 'पृष्ठस्थानान्तर' ],
-       'Mycontributions'           => [ 'मदीययोगदानम्' ],
-       'Mypage'                    => [ 'मम_पृष्टम्' ],
-       'Mytalk'                    => [ 'मदीयसंवादम्' ],
-       'Newimages'                 => [ 'नूतनसंचिका', 'नूतनचित्रानि' ],
-       'Newpages'                  => [ 'नूतनपृष्टानि' ],
-       'PasswordReset'             => [ 'सङ्केतशब्दपुन:प्रयु्क्ता' ],
+       'Allmessages'               => [ 'सरà¥\8dवसनà¥\8dदà¥\87शाà¤\83', 'सरà¥\8dवपà¥\8dरणालà¥\80-सà¤\82दà¥\87श' ],
+       'Allpages'                  => [ 'सरà¥\8dवपà¥\83षà¥\8dठानि', 'सरà¥\8dवपà¥\83षà¥\8dà¤\9fानि' ],
+       'Ancientpages'              => [ 'पà¥\81रातनपà¥\83षà¥\8dठानि', 'पà¥\82रà¥\8dवतनपà¥\83षà¥\8dà¤\9fानि' ],
+       'Blankpage'                 => [ 'रिक्तपृष्ठानि', 'रिक्तपृष्ठ' ],
+       'Block'                     => [ 'पà¥\8dरतिबनà¥\8dधà¤\83', 'सदसà¥\8dयपà¥\8dरतिबनà¥\8dध' ],
+       'Booksources'               => [ 'पुस्तकस्रोतांसि', 'पुस्तकस्रोत' ],
+       'BrokenRedirects'           => [ 'भà¤\97à¥\8dनानि_à¤\85नà¥\81पà¥\8dरà¥\87षणानि', 'à¤\96णà¥\8dडà¥\80तपà¥\81नरà¥\8dनिरà¥\8dदà¥\87शन' ],
+       'Categories'                => [ 'वरà¥\8dà¤\97ाà¤\83', 'वरà¥\8dà¤\97à¤\83' ],
+       'ChangePassword'            => [ 'à¤\95à¥\82à¤\9fशबà¥\8dदà¤\83_परिवरà¥\8dतà¥\8dयतामà¥\8d', 'सà¤\99à¥\8dà¤\95à¥\87तशबà¥\8dदपà¥\81न:पà¥\8dरयà¥\81à¤\95à¥\8dता' ],
+       'Confirmemail'              => [ 'विपतà¥\8dरà¤\82_पà¥\81षà¥\8dà¤\9fà¥\8dयतामà¥\8d', 'विपतà¥\8dरपà¥\81षà¥\8dà¤\9fिà¤\95à¥\83तà¥\87' ],
+       'Contributions'             => [ 'यà¥\8bà¤\97दानानि', 'यà¥\8bà¤\97दानमà¥\8d' ],
+       'CreateAccount'             => [ 'लà¥\87à¤\96ा_सà¥\83à¤\9cà¥\8dयतामà¥\8d', 'सà¥\83à¤\9cà¥\8dà¤\89पयà¥\8bà¤\9cà¤\95सà¤\82à¤\9cà¥\8dà¤\9eा' ],
+       'Deadendpages'              => [ 'मà¥\83तानि_पà¥\83षà¥\8dठानि', 'निराà¤\97à¥\8dरपà¥\83षà¥\8dà¤\9fानि' ],
+       'DeletedContributions'      => [ 'à¤\85पाà¤\95à¥\83तानि_यà¥\8bà¤\97दानानि', 'परितà¥\8dयाà¤\97ितयà¥\8bà¤\97दान' ],
+       'DoubleRedirects'           => [ 'दà¥\8dवà¥\88धपà¥\81नरà¥\8dनिरà¥\8dदà¥\87शनमà¥\8d', 'पà¥\81नरà¥\8dनिरà¥\8dदà¥\87शनदà¥\8dवà¤\82दà¥\8dव' ],
+       'Emailuser'                 => [ 'विपतà¥\8dरपà¥\8dरयà¥\8bà¤\95à¥\8dता', 'विपतà¥\8dरयà¥\8bà¤\9cà¤\95' ],
+       'ExpandTemplates'           => [ 'फलà¤\95ानि_विसà¥\8dतà¥\80रà¥\8dयनà¥\8dतामà¥\8d', 'बिà¤\82बधरविसà¥\8dतारà¤\95रà¥\8bसि' ],
+       'Export'                    => [ 'निरà¥\8dयापयतà¥\81', 'निरà¥\8dयात' ],
+       'Fewestrevisions'           => [ 'सà¥\8dवलà¥\8dपतमपरिवरà¥\8dतानानि', 'सà¥\8dवलà¥\8dपपरिवरà¥\8dतन' ],
+       'FileDuplicateSearch'       => [ 'समानसà¤\9eà¥\8dà¤\9aिà¤\95ानà¥\8dवà¥\87षणमà¥\8d', 'à¤\85नà¥\81à¤\95à¥\83तसà¤\82à¤\9aिà¤\95ाशà¥\8bध' ],
+       'Filepath'                  => [ 'सà¤\9eà¥\8dà¤\9aिà¤\95ापथà¤\83', 'सà¤\82à¤\9aिà¤\95ापथ' ],
+       'Import'                    => [ 'à¤\86यापयतà¥\81', 'à¤\86यात' ],
+       'Invalidateemail'           => [ 'विपतà¥\8dरà¥\87ऽमानà¥\8dयमà¥\8d', 'à¤\85मानà¥\8dयविपतà¥\8dर' ],
+       'BlockList'                 => [ 'पà¥\8dरतिबनà¥\8dधावलिà¤\83', 'पà¥\8dरतिबनà¥\8dधसà¥\82à¤\9aà¥\80' ],
+       'LinkSearch'                => [ 'परिसनà¥\8dधà¥\87à¤\83_à¤\85नà¥\8dवà¥\87षणमà¥\8d', 'समà¥\8dबनà¥\8dधनà¥\8dâ\80\8cशà¥\8bध' ],
+       'Listadmins'                => [ 'पà¥\8dरबनà¥\8dधà¤\95ावलिà¤\83', 'पà¥\8dरà¤\9aालà¤\95सà¥\82à¤\9aà¥\80' ],
+       'Listbots'                  => [ 'बà¥\89à¤\9fसà¥\82à¤\9aà¥\80', 'सà¥\8dवयà¤\82à¤\85नà¥\81à¤\95à¥\83सà¥\82à¤\9aà¥\80' ],
+       'Listfiles'                 => [ 'सà¤\9eà¥\8dà¤\9aिà¤\95ावलिà¤\83', 'à¤\9aितà¥\8dरसà¥\82à¤\9aà¥\80', 'सà¤\82à¤\9aिà¤\95ासà¥\82à¤\9aि' ],
+       'Listgrouprights'           => [ 'समà¥\82हाधिà¤\95ारावलिà¤\83', 'à¤\97à¤\9fà¤\85धिà¤\95ारसà¥\82à¤\9aà¥\80' ],
+       'Listredirects'             => [ 'à¤\85नà¥\81पà¥\8dरà¥\87षितावलिà¤\83', 'विà¤\9aालनà¥\8dâ\80\8cसà¥\82à¤\9aà¥\80' ],
+       'Listusers'                 => [ 'सदसà¥\8dयावलिà¤\83', 'सदसà¥\8dयासà¥\82à¤\9aà¥\80' ],
+       'Lockdb'                    => [ 'दतà¥\8dताà¤\82शà¤\95à¥\80लनमà¥\8d', 'विदादà¥\8dवारà¤\82बनà¥\8dधà¥\8d' ],
+       'Log'                       => [ 'सà¤\82रà¤\95à¥\8dषितावलिà¤\83', 'à¤\85à¤\99à¥\8dà¤\95न' ],
+       'Lonelypages'               => [ 'à¤\8fà¤\95ाà¤\95िपà¥\83षà¥\8dठानि', 'à¤\85à¤\95लपà¥\83षà¥\8dà¤\9fानि' ],
+       'Longpages'                 => [ 'दà¥\80रà¥\8dà¤\98पà¥\83षà¥\8dठानि', 'दà¥\80रà¥\8dà¤\98पà¥\83षà¥\8dà¤\9fानि' ],
+       'MergeHistory'              => [ 'à¤\87तिहासविलयà¤\83', 'à¤\87तिहाससà¤\82यà¥\8bà¤\97' ],
+       'MIMEsearch'                => [ 'MIME_अन्वेषणम्', 'विविधामाप_(माईम)_शोधसि' ],
+       'Mostcategories'            => [ 'अधिकतमवर्गाः', 'अधिकतमवर्ग' ],
+       'Mostimages'                => [ 'à¤\85धिà¤\95तमसà¤\9eà¥\8dà¤\9aिà¤\95ाà¤\83', 'à¤\85धिà¤\95तमसमà¥\8dभनà¥\8dदिनà¥\8d_सà¤\82à¤\9aिà¤\95ा' ],
+       'Mostlinked'                => [ 'à¤\85धिà¤\95तमपरिसनà¥\8dधितमà¥\8d', 'à¤\85धिà¤\95तमसमà¥\8dभनà¥\8dदिनà¥\8d_पà¥\83षà¥\8dà¤\9fानि', 'à¤\85धिà¤\95तमसमà¥\8dभनà¥\8dदिनà¥\8d' ],
+       'Mostlinkedcategories'      => [ 'à¤\85धिà¤\95तमपरिसनà¥\8dधितवरà¥\8dà¤\97ाà¤\83', 'à¤\85धिà¤\95तमसमà¥\8dभनà¥\8dदिनà¥\8d_वरà¥\8dà¤\97' ],
+       'Mostlinkedtemplates'       => [ 'à¤\85धिà¤\95तमपरिसनà¥\8dधितफलà¤\95ानि', 'à¤\85धिà¤\95तमसमà¥\8dभनà¥\8dदिनà¥\8d_फलà¤\95ानि' ],
+       'Mostrevisions'             => [ 'à¤\85धिà¤\95तमसà¤\82सà¥\8dà¤\95रणानि', 'à¤\85धिà¤\95तमपरिवरà¥\8dतन' ],
+       'Movepage'                  => [ 'पृष्ठस्थानान्तरणम्', 'पृष्ठस्थानान्तर' ],
+       'Mycontributions'           => [ 'मम_यà¥\8bà¤\97दानानि', 'मदà¥\80ययà¥\8bà¤\97दानमà¥\8d' ],
+       'Mypage'                    => [ 'मम_पà¥\83षà¥\8dठमà¥\8d', 'मम_पà¥\83षà¥\8dà¤\9fमà¥\8d' ],
+       'Mytalk'                    => [ 'मम_समà¥\8dभाषणमà¥\8d', 'मदà¥\80यसà¤\82वादमà¥\8d' ],
+       'Newimages'                 => [ 'नवà¥\80नà¤\9aितà¥\8dराणि', 'नà¥\82तनसà¤\82à¤\9aिà¤\95ा', 'नà¥\82तनà¤\9aितà¥\8dरानि' ],
+       'Newpages'                  => [ 'नवà¥\80नपà¥\83षà¥\8dठानि', 'नà¥\82तनपà¥\83षà¥\8dà¤\9fानि' ],
+       'PasswordReset'             => [ 'à¤\95à¥\82à¤\9fशबà¥\8dदसà¥\8dय_पà¥\81नसà¥\8dसà¥\8dथापनमà¥\8d', 'सà¤\99à¥\8dà¤\95à¥\87तशबà¥\8dदपà¥\81न:पà¥\8dरयà¥\81à¥\8dà¤\95à¥\8dता' ],
        'Preferences'               => [ 'इष्टतमानि' ],
-       'Prefixindex'               => [ 'उपसर्गअनुक्रमणी' ],
-       'Protectedpages'            => [ 'सुरक्षितपृष्टानि' ],
-       'Protectedtitles'           => [ 'सुरक्षितशिर्षकम्' ],
-       'Randompage'                => [ 'अविशीष्टपृष्ठम्' ],
-       'RandomInCategory'          => [ 'अविशिष्टवर्ग' ],
-       'Randomredirect'            => [ 'अविशीष्टविचालन्‌' ],
-       'Recentchanges'             => [ 'नवीनतम_परिवर्तन' ],
-       'Recentchangeslinked'       => [ 'नवीनतमसम्भन्दिन_परिवर्त' ],
-       'Revisiondelete'            => [ 'आवृत्तीपरित्याग' ],
-       'Search'                    => [ 'शोध' ],
-       'Shortpages'                => [ 'लघुपृष्टानि' ],
-       'Specialpages'              => [ 'विशेषपृष्टानि' ],
-       'Statistics'                => [ 'सांख्यिकी' ],
-       'Uncategorizedcategories'   => [ 'अवर्गीकृतवर्ग' ],
-       'Uncategorizedimages'       => [ 'अवर्गीकृतसंचिका', 'अवर्गीकृतचित्रानि' ],
-       'Uncategorizedpages'        => [ 'अवर्गीकृतपृष्टानि' ],
+       'Prefixindex'               => [ 'à¤\89पसरà¥\8dà¤\97ानà¥\81à¤\95à¥\8dरमणà¥\80', 'à¤\89पसरà¥\8dà¤\97à¤\85नà¥\81à¤\95à¥\8dरमणà¥\80' ],
+       'Protectedpages'            => [ 'सà¥\81रà¤\95à¥\8dषितपà¥\83षà¥\8dठानि', 'सà¥\81रà¤\95à¥\8dषितपà¥\83षà¥\8dà¤\9fानि' ],
+       'Protectedtitles'           => [ 'सà¥\81रà¤\95à¥\8dषितशà¥\80रà¥\8dषà¤\95ाणि', 'सà¥\81रà¤\95à¥\8dषितशिरà¥\8dषà¤\95मà¥\8d' ],
+       'Randompage'                => [ 'यादà¥\83à¤\9aà¥\8dà¤\9bिà¤\95पà¥\83षà¥\8dठमà¥\8d', 'à¤\85विशà¥\80षà¥\8dà¤\9fपà¥\83षà¥\8dठमà¥\8d' ],
+       'RandomInCategory'          => [ 'वरà¥\8dà¤\97à¥\87_यादà¥\83à¤\9aà¥\8dà¤\9bिà¤\95मà¥\8d', 'à¤\85विशिषà¥\8dà¤\9fवरà¥\8dà¤\97' ],
+       'Randomredirect'            => [ 'यादà¥\83à¤\9aà¥\8dà¤\9bिà¤\95ानà¥\81पà¥\8dरà¥\87षितमà¥\8d', 'à¤\85विशà¥\80षà¥\8dà¤\9fविà¤\9aालनà¥\8dâ\80\8c' ],
+       'Recentchanges'             => [ 'नà¥\82तनपरिवरà¥\8dतनानि', 'नवà¥\80नतम_परिवरà¥\8dतन' ],
+       'Recentchangeslinked'       => [ 'नà¥\82तनपरिवरà¥\8dतनानाà¤\82_परिसनà¥\8dधयà¤\83', 'नवà¥\80नतमसमà¥\8dभनà¥\8dदिन_परिवरà¥\8dत' ],
+       'Revisiondelete'            => [ 'सà¤\82सà¥\8dà¤\95रणापाà¤\95रणमà¥\8d', 'à¤\86वà¥\83तà¥\8dतà¥\80परितà¥\8dयाà¤\97' ],
+       'Search'                    => [ 'à¤\85नà¥\8dवà¥\87षणमà¥\8d', 'शà¥\8bध' ],
+       'Shortpages'                => [ 'लà¤\98à¥\81पà¥\83षà¥\8dठानि', 'लà¤\98à¥\81पà¥\83षà¥\8dà¤\9fानि' ],
+       'Specialpages'              => [ 'विशà¥\87षपà¥\83षà¥\8dठानि', 'विशà¥\87षपà¥\83षà¥\8dà¤\9fानि' ],
+       'Statistics'                => [ 'साà¤\99à¥\8dà¤\96à¥\8dयिà¤\95à¥\80', 'साà¤\82à¤\96à¥\8dयिà¤\95à¥\80' ],
+       'Uncategorizedcategories'   => [ 'अवर्गीकृतवर्गाः', 'अवर्गीकृतवर्ग' ],
+       'Uncategorizedimages'       => [ 'à¤\85वरà¥\8dà¤\97à¥\80à¤\95à¥\83तà¤\9aितà¥\8dराणि', 'à¤\85वरà¥\8dà¤\97à¥\80à¤\95à¥\83तसà¤\82à¤\9aिà¤\95ा', 'à¤\85वरà¥\8dà¤\97à¥\80à¤\95à¥\83तà¤\9aितà¥\8dरानि' ],
+       'Uncategorizedpages'        => [ 'à¤\85वरà¥\8dà¤\97à¥\80à¤\95à¥\83तपà¥\83षà¥\8dठानि', 'à¤\85वरà¥\8dà¤\97à¥\80à¤\95à¥\83तपà¥\83षà¥\8dà¤\9fानि' ],
        'Uncategorizedtemplates'    => [ 'अवर्गीकृतफलकानि' ],
-       'Undelete'                  => [ 'प्रत्यादिश्_परित्याग' ],
-       'Unlockdb'                  => [ 'विवृतविदाद्वारंतालक' ],
-       'Unusedcategories'          => [ 'अप्रयूक्तवर्ग' ],
-       'Unusedimages'              => [ 'अप्रयूक्तसंचिका' ],
-       'Unusedtemplates'           => [ 'अप्रयूक्तबिंबधर' ],
-       'Unwatchedpages'            => [ 'अनिरिक्षीतपृष्ठ' ],
-       'Upload'                    => [ 'भारंन्यस्यति' ],
-       'Userlogin'                 => [ 'सदस्यप्रवेशन' ],
-       'Userlogout'                => [ 'सदस्यबहिर्गमन' ],
-       'Userrights'                => [ 'योजकआधिकार' ],
-       'Version'                   => [ 'आवृत्ती' ],
-       'Wantedcategories'          => [ 'प्रार्थितवर्ग' ],
-       'Wantedfiles'               => [ 'प्रार्थितसंचिका' ],
-       'Wantedpages'               => [ 'प्रार्थितपृष्टानि' ],
-       'Wantedtemplates'           => [ 'प्रार्थितफलकानि' ],
-       'Watchlist'                 => [ 'निरीक्षा_सूची' ],
-       'Whatlinkshere'             => [ 'किमपृष्ठ_सम्बद्धंकरोति' ],
-       'Withoutinterwiki'          => [ 'आन्तरविकिहीन' ],
+       'Undelete'                  => [ 'पà¥\81नसà¥\8dसà¥\8dथापनमà¥\8d', 'पà¥\8dरतà¥\8dयादिशà¥\8d_परितà¥\8dयाà¤\97' ],
+       'Unlockdb'                  => [ 'दतà¥\8dताà¤\82शà¥\8bदà¥\8dà¤\98ाà¤\9fनमà¥\8d', 'विवà¥\83तविदादà¥\8dवारà¤\82तालà¤\95' ],
+       'Unusedcategories'          => [ 'à¤\85पà¥\8dरयà¥\81à¤\95à¥\8dतवरà¥\8dà¤\97ाà¤\83', 'à¤\85पà¥\8dरयà¥\82à¤\95à¥\8dतवरà¥\8dà¤\97' ],
+       'Unusedimages'              => [ 'à¤\85पà¥\8dरयà¥\81à¤\95à¥\8dतà¤\9aितà¥\8dराणि', 'à¤\85पà¥\8dरयà¥\82à¤\95à¥\8dतसà¤\82à¤\9aिà¤\95ा' ],
+       'Unusedtemplates'           => [ 'à¤\85पà¥\8dरयà¥\81à¤\95à¥\8dतफलà¤\95ानि', 'à¤\85पà¥\8dरयà¥\82à¤\95à¥\8dतबिà¤\82बधर' ],
+       'Unwatchedpages'            => [ 'à¤\85निरà¥\80à¤\95à¥\8dषितपà¥\83षà¥\8dठानि', 'à¤\85निरिà¤\95à¥\8dषà¥\80तपà¥\83षà¥\8dठ' ],
+       'Upload'                    => [ 'à¤\89पारà¥\8bपणमà¥\8d', 'भारà¤\82नà¥\8dयसà¥\8dयति' ],
+       'Userlogin'                 => [ 'सदसà¥\8dयपà¥\8dरवà¥\87शà¤\83', 'सदसà¥\8dयपà¥\8dरवà¥\87शन' ],
+       'Userlogout'                => [ 'सदसà¥\8dयनिरà¥\8dà¤\97मनमà¥\8d', 'सदसà¥\8dयबहिरà¥\8dà¤\97मन' ],
+       'Userrights'                => [ 'सदसà¥\8dयाधिà¤\95ाराà¤\83', 'यà¥\8bà¤\9cà¤\95à¤\86धिà¤\95ार' ],
+       'Version'                   => [ 'सà¤\82सà¥\8dà¤\95रणमà¥\8d', 'à¤\86वà¥\83तà¥\8dतà¥\80' ],
+       'Wantedcategories'          => [ 'वाà¤\9eà¥\8dà¤\9bितवरà¥\8dà¤\97ाà¤\83', 'पà¥\8dरारà¥\8dथितवरà¥\8dà¤\97' ],
+       'Wantedfiles'               => [ 'वाà¤\9eà¥\8dà¤\9bितसà¤\9eà¥\8dà¤\9aिà¤\95ाà¤\83', 'पà¥\8dरारà¥\8dथितसà¤\82à¤\9aिà¤\95ा' ],
+       'Wantedpages'               => [ 'वाà¤\9eà¥\8dà¤\9bितपà¥\83षà¥\8dठानि', 'पà¥\8dरारà¥\8dथितपà¥\83षà¥\8dà¤\9fानि' ],
+       'Wantedtemplates'           => [ 'वाà¤\9eà¥\8dà¤\9bितफलà¤\95ानि', 'पà¥\8dरारà¥\8dथितफलà¤\95ानि' ],
+       'Watchlist'                 => [ 'निरीक्षा_सूची', 'निरीक्षासूचिः' ],
+       'Whatlinkshere'             => [ 'à¤\95िमतà¥\8dर_सà¤\81लà¥\8dलà¤\97à¥\8dनमà¥\8d', 'à¤\95िमपà¥\83षà¥\8dठ_समà¥\8dबदà¥\8dधà¤\82à¤\95रà¥\8bति' ],
+       'Withoutinterwiki'          => [ 'à¤\85नà¥\8dतरà¥\8dविà¤\95िपरिसनà¥\8dधिहà¥\80नमà¥\8d', 'à¤\86नà¥\8dतरविà¤\95िहà¥\80न' ],
 ];
 
 $magicWords = [
index d88d5e9..0670454 100644 (file)
@@ -187,13 +187,7 @@ TEXT
                                }
                                # cl_type will be wrong for lots of pages if cl_collation is 0,
                                # so let's update it while we're here.
-                               if ( $title->getNamespace() == NS_CATEGORY ) {
-                                       $type = 'subcat';
-                               } elseif ( $title->getNamespace() == NS_FILE ) {
-                                       $type = 'file';
-                               } else {
-                                       $type = 'page';
-                               }
+                               $type = MWNamespace::getCategoryLinkType( $title->getNamespace() );
                                $newSortKey = $collation->getSortKey(
                                        $title->getCategorySortkey( $prefix ) );
                                if ( $verboseStats ) {
index 65860ea..1b37ec3 100644 (file)
@@ -54,3 +54,9 @@
 .mw-changeslist-legend.mw-collapsed + h4 + div > table.mw-changeslist-line:first-child {
        clear: right;
 }
+
+/* Hide RCFilters highlight containers if RCFilters is not enabled.
+   This is overridden in mw.ui.rcfilters.ChangesListWrapperWidget.less if RCFilters is enabled. */
+.mw-rcfilters-ui-highlights {
+       display: none;
+}
index 15e2def..1b91a87 100644 (file)
@@ -575,4 +575,34 @@ class MWNamespaceTest extends MediaWikiTestCase {
        private function assertDifferentSubject( $ns1, $ns2, $msg = '' ) {
                $this->assertFalse( MWNamespace::subjectEquals( $ns1, $ns2 ), $msg );
        }
+
+       public function provideGetCategoryLinkType() {
+               return [
+                       [ NS_MAIN, 'page' ],
+                       [ NS_TALK, 'page' ],
+                       [ NS_USER, 'page' ],
+                       [ NS_USER_TALK, 'page' ],
+
+                       [ NS_FILE, 'file' ],
+                       [ NS_FILE_TALK, 'page' ],
+
+                       [ NS_CATEGORY, 'subcat' ],
+                       [ NS_CATEGORY_TALK, 'page' ],
+
+                       [ 100, 'page' ],
+                       [ 101, 'page' ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideGetCategoryLinkType
+        * @covers MWNamespace::getCategoryLinkType
+        *
+        * @param int $index
+        * @param string $expected
+        */
+       public function testGetCategoryLinkType( $index, $expected ) {
+               $actual = MWNamespace::getCategoryLinkType( $index );
+               $this->assertSame( $expected, $actual, "NS $index" );
+       }
 }
index 93c7ed3..cf48215 100644 (file)
@@ -5,6 +5,7 @@ use MediaWiki\Interwiki\InterwikiLookup;
 use MediaWiki\Linker\LinkRenderer;
 use MediaWiki\Linker\LinkRendererFactory;
 use MediaWiki\MediaWikiServices;
+use MediaWiki\Preferences\PreferencesFactory;
 use MediaWiki\Services\DestructibleService;
 use MediaWiki\Services\SalvageableService;
 use MediaWiki\Services\ServiceDisabledException;
@@ -12,8 +13,10 @@ use MediaWiki\Shell\CommandFactory;
 use MediaWiki\Storage\BlobStore;
 use MediaWiki\Storage\BlobStoreFactory;
 use MediaWiki\Storage\NameTableStore;
+use MediaWiki\Storage\RevisionFactory;
 use MediaWiki\Storage\RevisionLookup;
 use MediaWiki\Storage\RevisionStore;
+use MediaWiki\Storage\RevisionStoreFactory;
 use MediaWiki\Storage\SqlBlobStore;
 
 /**
@@ -305,8 +308,6 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
 
        public function provideGetService() {
                // NOTE: This should list all service getters defined in ServiceWiring.php.
-               // NOTE: For every test case defined here there should be a corresponding
-               // test case defined in provideGetters().
                return [
                        'BootstrapConfig' => [ 'BootstrapConfig', Config::class ],
                        'ConfigFactory' => [ 'ConfigFactory', ConfigFactory::class ],
@@ -346,10 +347,23 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
                        'BlobStore' => [ 'BlobStore', BlobStore::class ],
                        '_SqlBlobStore' => [ '_SqlBlobStore', SqlBlobStore::class ],
                        'RevisionStore' => [ 'RevisionStore', RevisionStore::class ],
+                       'RevisionStoreFactory' => [ 'RevisionStoreFactory', RevisionStoreFactory::class ],
                        'RevisionLookup' => [ 'RevisionLookup', RevisionLookup::class ],
+                       'RevisionFactory' => [ 'RevisionFactory', RevisionFactory::class ],
+                       'ContentModelStore' => [ 'ContentModelStore', NameTableStore::class ],
+                       'SlotRoleStore' => [ 'SlotRoleStore', NameTableStore::class ],
                        'HttpRequestFactory' => [ 'HttpRequestFactory', HttpRequestFactory::class ],
                        'CommentStore' => [ 'CommentStore', CommentStore::class ],
                        'ChangeTagDefStore' => [ 'ChangeTagDefStore', NameTableStore::class ],
+                       'ConfiguredReadOnlyMode' => [ 'ConfiguredReadOnlyMode', ConfiguredReadOnlyMode::class ],
+                       'ReadOnlyMode' => [ 'ReadOnlyMode', ReadOnlyMode::class ],
+                       'UploadRevisionImporter' => [ 'UploadRevisionImporter', UploadRevisionImporter::class ],
+                       'OldRevisionImporter' => [ 'OldRevisionImporter', OldRevisionImporter::class ],
+                       'WikiRevisionOldRevisionImporterNoUpdates' =>
+                               [ 'WikiRevisionOldRevisionImporterNoUpdates', ImportableOldRevisionImporter::class ],
+                       'ExternalStoreFactory' => [ 'ExternalStoreFactory', ExternalStoreFactory::class ],
+                       'PreferencesFactory' => [ 'PreferencesFactory', PreferencesFactory::class ],
+                       'ActorMigration' => [ 'ActorMigration', ActorMigration::class ],
                ];
        }
 
@@ -378,4 +392,15 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
                }
        }
 
+       public function testDefaultServiceWiringServicesHaveTests() {
+               global $IP;
+               $testedServices = array_keys( $this->provideGetService() );
+               $allServices = array_keys( include $IP . '/includes/ServiceWiring.php' );
+               $this->assertEquals(
+                       [],
+                       array_diff( $allServices, $testedServices ),
+                       'The following services have not been added to MediaWikiServicesTest::provideGetService'
+               );
+       }
+
 }
diff --git a/tests/phpunit/includes/Storage/RevisionStoreFactoryTest.php b/tests/phpunit/includes/Storage/RevisionStoreFactoryTest.php
new file mode 100644 (file)
index 0000000..a5c18ac
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+
+namespace MediaWiki\Tests\Storage;
+
+use ActorMigration;
+use CommentStore;
+use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\Storage\NameTableStore;
+use MediaWiki\Storage\RevisionStore;
+use MediaWiki\Storage\RevisionStoreFactory;
+use MediaWiki\Storage\SqlBlobStore;
+use MediaWikiTestCase;
+use WANObjectCache;
+use Wikimedia\Rdbms\LoadBalancer;
+use Wikimedia\TestingAccessWrapper;
+
+class RevisionStoreFactoryTest extends MediaWikiTestCase {
+
+       public function testValidConstruction_doesntCauseErrors() {
+               new RevisionStoreFactory(
+                       $this->getMockLoadBalancer(),
+                       $this->getMockSqlBlobStore(),
+                       $this->getHashWANObjectCache(),
+                       $this->getMockCommentStore(),
+                       $this->getMockNameTableStore(),
+                       $this->getMockNameTableStore(),
+                       MIGRATION_OLD,
+                       ActorMigration::newMigration(),
+                       LoggerFactory::getInstance( 'someInstance' ),
+                       true
+               );
+               $this->assertTrue( true );
+       }
+
+       public function provideWikiIds() {
+               yield [ true ];
+               yield [ false ];
+               yield [ 'somewiki' ];
+               yield [ 'somewiki', MIGRATION_OLD , false ];
+               yield [ 'somewiki', MIGRATION_NEW , true ];
+       }
+
+       /**
+        * @dataProvider provideWikiIds
+        */
+       public function testGetRevisionStore(
+               $wikiId,
+               $mcrMigrationStage = MIGRATION_OLD,
+               $contentHandlerUseDb = true
+       ) {
+               $lb = $this->getMockLoadBalancer();
+               $blobStore = $this->getMockSqlBlobStore();
+               $cache = $this->getHashWANObjectCache();
+               $commentStore = $this->getMockCommentStore();
+               $contentModelStore = $this->getMockNameTableStore();
+               $slotRoleStore = $this->getMockNameTableStore();
+               $actorMigration = ActorMigration::newMigration();
+               $logger = LoggerFactory::getInstance( 'someInstance' );
+
+               $factory = new RevisionStoreFactory(
+                       $lb,
+                       $blobStore,
+                       $cache,
+                       $commentStore,
+                       $contentModelStore,
+                       $slotRoleStore,
+                       $mcrMigrationStage,
+                       $actorMigration,
+                       $logger,
+                       $contentHandlerUseDb
+               );
+
+               $store = $factory->getRevisionStore( $wikiId );
+               $wrapper = TestingAccessWrapper::newFromObject( $store );
+
+               // ensure the correct object type is returned
+               $this->assertInstanceOf( RevisionStore::class, $store );
+
+               // ensure the RevisionStore is for the given wikiId
+               $this->assertSame( $wikiId, $wrapper->wikiId );
+
+               // ensure all other required services are correctly set
+               $this->assertSame( $lb, $wrapper->loadBalancer );
+               $this->assertSame( $blobStore, $wrapper->blobStore );
+               $this->assertSame( $cache, $wrapper->cache );
+               $this->assertSame( $commentStore, $wrapper->commentStore );
+               $this->assertSame( $contentModelStore, $wrapper->contentModelStore );
+               $this->assertSame( $slotRoleStore, $wrapper->slotRoleStore );
+               $this->assertSame( $mcrMigrationStage, $wrapper->mcrMigrationStage );
+               $this->assertSame( $actorMigration, $wrapper->actorMigration );
+               $this->assertSame( $logger, $wrapper->logger );
+               $this->assertSame( $contentHandlerUseDb, $store->getContentHandlerUseDB() );
+       }
+
+       /**
+        * @return \PHPUnit_Framework_MockObject_MockObject|NameTableStore
+        */
+       private function getMockNameTableStore() {
+               return $this->getMockBuilder( NameTableStore::class )
+                       ->disableOriginalConstructor()->getMock();
+       }
+
+       /**
+        * @return \PHPUnit_Framework_MockObject_MockObject|LoadBalancer
+        */
+       private function getMockLoadBalancer() {
+               return $this->getMockBuilder( LoadBalancer::class )
+                       ->disableOriginalConstructor()->getMock();
+       }
+
+       /**
+        * @return \PHPUnit_Framework_MockObject_MockObject|SqlBlobStore
+        */
+       private function getMockSqlBlobStore() {
+               return $this->getMockBuilder( SqlBlobStore::class )
+                       ->disableOriginalConstructor()->getMock();
+       }
+
+       /**
+        * @return \PHPUnit_Framework_MockObject_MockObject|CommentStore
+        */
+       private function getMockCommentStore() {
+               return $this->getMockBuilder( CommentStore::class )
+                       ->disableOriginalConstructor()->getMock();
+       }
+
+       private function getHashWANObjectCache() {
+               return new WANObjectCache( [ 'cache' => new \HashBagOStuff() ] );
+       }
+
+}
index 63cf02f..e0364c4 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
 use MediaWiki\Storage\RevisionSlotsUpdate;
 use Wikimedia\TestingAccessWrapper;
 
@@ -1028,6 +1029,9 @@ more stuff
                // Use the confirmed group for user2 to make sure the user is different
                $user2 = $this->getTestUser( [ 'confirmed' ] )->getUser();
 
+               // make sure we can test autopatrolling
+               $this->setMwGlobals( 'wgUseRCPatrol', true );
+
                // TODO: MCR: test rollback of multiple slots!
                $page = $this->newPage( __METHOD__ );
 
@@ -1085,61 +1089,21 @@ more stuff
                        "rollback did not revert to the correct revision" );
                $this->assertEquals( "one\n\ntwo", $page->getContent()->getNativeData() );
 
-               // TODO: MCR: assert origin once we write slot data
-               // $mainSlot = $page->getRevision()->getRevisionRecord()->getSlot( 'main' );
-               // $this->assertTrue( $mainSlot->isInherited(), 'isInherited' );
-               // $this->assertSame( $rev2->getId(), $mainSlot->getOrigin(), 'getOrigin' );
-       }
-
-       /**
-        * @covers WikiPage::doRollback
-        * @covers WikiPage::commitRollback
-        */
-       public function testDoRollback_simple() {
-               $admin = $this->getTestSysop()->getUser();
-
-               $text = "one";
-               $page = $this->newPage( __METHOD__ );
-               $page->doEditContent(
-                       ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
-                       "section one",
-                       EDIT_NEW,
-                       false,
-                       $admin
-               );
-               $rev1 = $page->getRevision();
-
-               $user1 = $this->getTestUser()->getUser();
-               $text .= "\n\ntwo";
-               $page = new WikiPage( $page->getTitle() );
-               $page->doEditContent(
-                       ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
-                       "adding section two",
-                       0,
-                       false,
-                       $user1
+               $rc = MediaWikiServices::getInstance()->getRevisionStore()->getRecentChange(
+                       $page->getRevision()->getRevisionRecord()
                );
 
-               # now, try the rollback
-               $token = $admin->getEditToken( 'rollback' );
-               $errors = $page->doRollback(
-                       $user1->getName(),
-                       "testing revert",
-                       $token,
-                       false,
-                       $details,
-                       $admin
+               $this->assertNotNull( $rc, 'RecentChanges entry' );
+               $this->assertEquals(
+                       RecentChange::PRC_AUTOPATROLLED,
+                       $rc->getAttribute( 'rc_patrolled' ),
+                       'rc_patrolled'
                );
 
-               if ( $errors ) {
-                       $this->fail( "Rollback failed:\n" . print_r( $errors, true )
-                               . ";\n" . print_r( $details, true ) );
-               }
-
-               $page = new WikiPage( $page->getTitle() );
-               $this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
-                       "rollback did not revert to the correct revision" );
-               $this->assertEquals( "one", $page->getContent()->getNativeData() );
+               // TODO: MCR: assert origin once we write slot data
+               // $mainSlot = $page->getRevision()->getRevisionRecord()->getSlot( 'main' );
+               // $this->assertTrue( $mainSlot->isInherited(), 'isInherited' );
+               // $this->assertSame( $rev2->getId(), $mainSlot->getOrigin(), 'getOrigin' );
        }
 
        /**