Merge "mw.Upload.BookletLayout: Update padding/margin to match OOUI to avoid scrollbars"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 4 Jul 2018 02:00:58 +0000 (02:00 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 4 Jul 2018 02:00:58 +0000 (02:00 +0000)
36 files changed:
.travis.yml
includes/Block.php
includes/GlobalFunctions.php
includes/MediaWikiServices.php
includes/OutputPage.php
includes/ServiceWiring.php
includes/Storage/DerivedPageDataUpdater.php
includes/api/i18n/uk.json
includes/filerepo/file/ArchivedFile.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/OldLocalFile.php
includes/libs/objectcache/RESTBagOStuff.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabaseSqlite.php
includes/libs/rdbms/loadbalancer/ILoadBalancer.php
includes/resourceloader/ResourceLoader.php
includes/search/SearchMssql.php
includes/session/SessionProviderInterface.php
includes/specials/pagers/DeletedContribsPager.php
languages/i18n/be-tarask.json
languages/i18n/ce.json
languages/i18n/is.json
languages/i18n/mni.json
languages/i18n/my.json
languages/i18n/pt.json
languages/i18n/sat.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/uk.json
languages/i18n/ur.json
maintenance/storage/recompressTracked.php
resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js
tests/parser/parserTests.txt
tests/phpunit/includes/MediaWikiServicesTest.php
tests/phpunit/includes/db/LoadBalancerTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseTest.php

index e15fc55..2fc6d64 100644 (file)
@@ -38,8 +38,11 @@ matrix:
     - env: dbtype=mysql dbuser=root
       php: hhvm-3.18
   allow_failures:
-    - php: hhvm-3.24
+    - php: 7.2
+    - env: dbtype=postgres dbuser=travis
+    - php: hhvm-3.18
     - php: hhvm-3.21
+    - php: hhvm-3.24
 
 services:
   - mysql
@@ -80,7 +83,8 @@ notifications:
   email: false
   irc:
     channels:
-      - "chat.freenode.net#mediawiki-feed"
+      - "chat.freenode.net#wikimedia-dev"
+    template:
+      - "%{repository}#%{build_number} (%{branch} - %{commit} %{author}): %{message} - %{build_url}"
     on_success: change
-    on_failure: change
-    skip_join: true
+    on_failure: always
index 9567b06..a7b8035 100644 (file)
@@ -224,7 +224,7 @@ class Block {
                        'ipb_address',
                        'ipb_by',
                        'ipb_by_text',
-                       'ipb_by_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'ipb_by_actor' : null,
+                       'ipb_by_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'ipb_by_actor' : 'NULL',
                        'ipb_timestamp',
                        'ipb_auto',
                        'ipb_anon_only',
index d9996f4..d0229bc 100644 (file)
@@ -31,6 +31,7 @@ use MediaWiki\MediaWikiServices;
 use MediaWiki\Shell\Shell;
 use Wikimedia\ScopedCallback;
 use Wikimedia\Rdbms\DBReplicationWaitError;
+use Wikimedia\WrappedString;
 
 /**
  * Load an extension
@@ -3103,6 +3104,7 @@ function wfShorthandToInteger( $string = '', $default = -1 ) {
  * @return string The language code which complying with BCP 47 standards.
  */
 function wfBCP47( $code ) {
+       wfDeprecated( __METHOD__, '1.31' );
        return LanguageCode::bcp47( $code );
 }
 
index caaa6b3..7cc2462 100644 (file)
@@ -467,6 +467,14 @@ class MediaWikiServices extends ServiceContainer {
                return $this->getService( 'StatsdDataFactory' );
        }
 
+       /**
+        * @since 1.32
+        * @return IBufferingStatsdDataFactory
+        */
+       public function getPerDbNameStatsdDataFactory() {
+               return $this->getService( 'PerDbNameStatsdDataFactory' );
+       }
+
        /**
         * @since 1.27
         * @return EventRelayerGroup
index 0b2ba40..4ce49fd 100644 (file)
@@ -24,6 +24,7 @@ use MediaWiki\Linker\LinkTarget;
 use MediaWiki\Logger\LoggerFactory;
 use MediaWiki\MediaWikiServices;
 use MediaWiki\Session\SessionManager;
+use Wikimedia\Rdbms\IResultWrapper;
 use Wikimedia\RelPath;
 use Wikimedia\WrappedString;
 use Wikimedia\WrappedStringList;
@@ -1337,7 +1338,7 @@ class OutputPage extends ContextSource {
 
        /**
         * @param array $categories
-        * @return bool|ResultWrapper
+        * @return bool|IResultWrapper
         */
        protected function addCategoryLinksToLBAndGetResult( array $categories ) {
                # Add the links to a LinkBatch
index ba576d5..9c2be7e 100644 (file)
@@ -128,6 +128,14 @@ return [
                );
        },
 
+       'PerDbNameStatsdDataFactory' => function ( MediaWikiServices $services ) {
+               $config = $services->getMainConfig();
+               $wiki = $config->get( 'DBname' );
+               return new BufferingStatsdDataFactory(
+                       rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' ) . $wiki
+               );
+       },
+
        'EventRelayerGroup' => function ( MediaWikiServices $services ) {
                return new EventRelayerGroup( $services->getMainConfig()->get( 'EventRelayerConfig' ) );
        },
index cc72754..8da812a 100644 (file)
@@ -1310,7 +1310,7 @@ class DerivedPageDataUpdater implements IDBAccessObject {
                                        // stale data from REPEATABLE-READ snapshots.
                                        // HACK: But don't use a fresh connection in unit tests, since it would not have
                                        // the fake tables. This should be handled by the LoadBalancer!
-                                       $flags = defined( 'MW_PHPUNIT_TEST' ) ? 0 : $lb::CONN_TRX_AUTO;
+                                       $flags = defined( 'MW_PHPUNIT_TEST' ) ? 0 : $lb::CONN_TRX_AUTOCOMMIT;
                                        $db = $lb->getConnectionRef( $dbIndex, [], $this->getWikiId(), $flags );
 
                                        return 1 + (int)$db->selectField(
index 59616c0..3039ef4 100644 (file)
@@ -16,7 +16,7 @@
                        "Choomaq"
                ]
        },
-       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Документація]]\n* [[mw:Special:MyLanguage/API:FAQ|ЧаПи]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Список розсилки]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Оголошення API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Баґи і запити]\n</div>\n<strong>Статус:</strong> Усі функції, вказані на цій сторінці, мають працювати, але API далі перебуває в активній розробці і може змінитися у будь-який момент. Підпишіться на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ список розсилки mediawiki-api-announce], щоб помічати оновлення.\n\n<strong>Хибні запити:</strong> Коли до API надсилаються хибні запити, буде відіслано HTTP-шапку з ключем «MediaWiki-API-Error», а тоді і значення шапки, і код помилки, надіслані назад, будуть встановлені з тим же значенням. Більше інформації див. на [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n\n<strong>Тестування:</strong> Для зручності тестування запитів API, див. [[Special:ApiSandbox]].",
+       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Документація]]\n* [[mw:Special:MyLanguage/API:FAQ|ЧаПи]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Список розсилки]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Оголошення API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Баґи і запити]\n</div>\n<strong>Статус:</strong> Усі функції, вказані на цій сторінці, мають працювати, але API далі перебуває в активній розробці і може змінитися у будь-який момент. Підпишіться на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ список розсилки mediawiki-api-announce], щоб помічати оновлення.\n\n<strong>Хибні запити:</strong> Коли до API надсилаються хибні запити, буде відіслано HTTP-шапку з ключем «MediaWiki-API-Error», а тоді і значення шапки, і код помилки, надіслані назад, будуть встановлені з тим же значенням. Більше інформації див. на сторінці [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Помилки й попередження]].\n\n<p class=\"mw-apisandbox-link\"><strong>Тестування:</strong> Для зручності тестування запитів API, див. [[Special:ApiSandbox]].</p>",
        "apihelp-main-param-action": "Яку дію виконати.",
        "apihelp-main-param-format": "Формат виводу.",
        "apihelp-main-param-maxlag": "Максимальна затримка може використовуватися, коли MediaWiki інстальовано на реплікований кластер бази даних. Щоб зберегти дії, які спричиняють більшу затримку реплікації, цей параметр може змусити клієнт почекати, поки затримка реплікації не буде меншою за вказане значення. У випадку непомірної затримки, видається код помилки <samp>maxlag</samp> з повідомленням на зразок <samp>Очікування на $host: $lag секунд(и) затримки</samp>.<br />Див. [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manual: Maxlag parameter]] для детальнішої інформації.",
@@ -67,6 +67,7 @@
        "apihelp-compare-param-fromid": "Перший ID сторінки для порівняння.",
        "apihelp-compare-param-fromrev": "Перша версія для порівняння.",
        "apihelp-compare-param-fromtext": "Використати цей текст замість контенту версії, вказаної через <var>fromtitle</var>, <var>fromid</var> або <var>fromrev</var>.",
+       "apihelp-compare-param-fromsection": "Використовувати лише вказану секцію із заданого вмісту «from».",
        "apihelp-compare-param-frompst": "Зробити трансформацію перед збереженням на <var>fromtext</var>.",
        "apihelp-compare-param-fromcontentmodel": "Контентна модель <var>fromtext</var>. Якщо не вказано, буде використано припущення на основі інших параметрів.",
        "apihelp-compare-param-fromcontentformat": "Формат серіалізації контенту <var>fromtext</var>.",
@@ -75,6 +76,7 @@
        "apihelp-compare-param-torev": "Друга версія для порівняння.",
        "apihelp-compare-param-torelative": "Використати версію, яка стосується версії, визначеної через <var>fromtitle</var>, <var>fromid</var> або <var>fromrev</var>. Усі інші опції 'to' буде проігноровано.",
        "apihelp-compare-param-totext": "Використати цей текст замість контенту версії, вказаної через <var>totitle</var>, <var>toid</var> або <var>torev</var>.",
+       "apihelp-compare-param-tosection": "Використовувати лише вказану секцію із заданого вмісту «to».",
        "apihelp-compare-param-topst": "Виконати трансформацію перед збереженням на <var>totext</var>.",
        "apihelp-compare-param-tocontentmodel": "Контентна модель <var>totext</var>. Якщо не вказано, буде використано припущення на основі інших параметрів.",
        "apihelp-compare-param-tocontentformat": "Формат серіалізації контенту <var>totext</var>.",
        "apihelp-import-extended-description": "Зважте, що HTTP POST має бути виконано як завантаження файлу (тобто з використанням даних різних частин/форм) під час надсилання файлу для параметра <var>xml</var>.",
        "apihelp-import-param-summary": "Підсумок імпорту записів журналу.",
        "apihelp-import-param-xml": "Завантажено XML-файл.",
+       "apihelp-import-param-interwikiprefix": "Для завантажених імпортів: префікс інтервікі, який слід додавати до невідомих імен користувачів (а також відомих користувачів, якщо задано <var>$1assignknownusers</var>).",
+       "apihelp-import-param-assignknownusers": "Прив'язувати редагування до локальних користувачів, якщо користувач із таким іменем існує локально.",
        "apihelp-import-param-interwikisource": "Для інтервікі-імпорту: вікі, з якої імпортувати.",
        "apihelp-import-param-interwikipage": "Для інтервікі-імпорту: сторінки для імпорту.",
        "apihelp-import-param-fullhistory": "Для інтервікі-імпорту: імпортувати повну історію, не лише поточну версію.",
        "apihelp-opensearch-summary": "Шукати у вікі з використанням протоколу OpenSearch.",
        "apihelp-opensearch-param-search": "Рядок пошуку.",
        "apihelp-opensearch-param-limit": "Максимальна кількість результатів для виведення.",
-       "apihelp-opensearch-param-namespace": "Простори назв, у яких шукати.",
+       "apihelp-opensearch-param-namespace": "Простори назв, у яких шукати. Ігнорується, якщо <var>$1search</var> починається з валідного префікса простору назв.",
        "apihelp-opensearch-param-suggest": "Нічого не робити, якщо <var>[[mw:Special:MyLanguage/Manual:$wgEnableOpenSearchSuggest|$wgEnableOpenSearchSuggest]]</var> хибний.",
        "apihelp-opensearch-param-redirects": "Як обробляти перенаправлення:\n;return:Видати саме перенаправлення.\n;resolve:Видати цільову сторінку. Може видати менше, ніж $1limit результат{{PLURAL:$1limit||и|ів}}.\nЗ історичних причин, за замовчуванням стоїть «return» для $1format=json і «resolve» — для інших форматів.",
        "apihelp-opensearch-param-format": "Формат виводу.",
        "apihelp-parse-param-disablepp": "Використати натомість <var>$1disablelimitreport</var>.",
        "apihelp-parse-param-disableeditsection": "Пропустити посилання на редагування розділів на виході аналізу.",
        "apihelp-parse-param-disabletidy": "Не запускайте очищення HTML (e.g. tidy) на виході аналізу.",
+       "apihelp-parse-param-disablestylededuplication": "Не усувайте дублікати вбудованих таблиць стилів на виході парсера.",
        "apihelp-parse-param-generatexml": "Генерувати синтаксичне дерево XML (передбачає модель вмісту <code>$1</code>; замінено на <kbd>$2prop=parsetree</kbd>).",
        "apihelp-parse-param-preview": "Аналізувати у режимі попереднього перегляду.",
        "apihelp-parse-param-sectionpreview": "Аналізувати у режимі попереднього перегляду розділу (також вмикає попередній перегляд).",
        "apihelp-query+filearchive-param-dir": "Напрямок, у якому перелічити.",
        "apihelp-query+filearchive-param-sha1": "SHA1-хеш зображення. Перевизначає $1sha1base36.",
        "apihelp-query+filearchive-param-sha1base36": "SHA1-хеш зображення у base 36 (використано в MediaWiki).",
+       "apihelp-query+filearchive-param-prop": "Інформацію про яке зображення слід отримати:",
        "apihelp-query+filearchive-paramvalue-prop-sha1": "Додає хеш SHA-1 до зображення.",
        "apihelp-query+filearchive-paramvalue-prop-timestamp": "Додає часову мітку завантаженої версії.",
        "apihelp-query+filearchive-paramvalue-prop-user": "Додає користувача, який завантажив версію зображення.",
        "apihelp-query+filearchive-paramvalue-prop-archivename": "Додає до імені версію архіву для неостаточного варіанту файлу.",
        "apihelp-query+filearchive-example-simple": "Показати список усіх вилучених файлів.",
        "apihelp-query+filerepoinfo-summary": "Видати мета-інформацію про репозиторії зображень, налаштовані на вікі.",
-       "apihelp-query+filerepoinfo-param-prop": "Які властивості репозиторію отримати (на деяких вікі може бути більше):\n;apiurl:URL до репозиторію API — корисне для отримання інформації про зображення з хосту.\n;name:Ключ репозиторію — використано в e.g. <var>[[mw:Special:MyLanguage/Manual:$wgForeignFileRepos|$wgForeignFileRepos]]</var> і значення [[Special:ApiHelp/query+imageinfo|imageinfo]].\n;displayname:Людиночита назва репозиторію вікі.\n;rooturl:Корінний URL для шляху зображення.\n;local:Чи репозиторій локальний, чи ні.",
+       "apihelp-query+filerepoinfo-param-prop": "Які властивості репозиторію отримати (доступні властивості можуть варіюватися в інших вікі).",
+       "apihelp-query+filerepoinfo-paramvalue-prop-apiurl": "URL-адреса API репозиторію — корисно для отримання інформації про зображення від хоста.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-articlepath": "<var>[[mw:Special:MyLanguage/Manual:$wgArticlePath|$wgArticlePath]]</var> вікі-сайту репозиторію, або еквівалент.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-canUpload": "Чи можна завантажувати файли в цей репозиторій, напр., через CORS та спільну автентифікацію.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-displayname": "Назва вікі-сайту репозиторію, читабельна для людини.",
        "apihelp-query+filerepoinfo-example-simple": "Отримати інформацію про репозиторії файлів.",
        "apihelp-query+fileusage-summary": "Знайти всі сторінки, що використовують дані файли.",
        "apihelp-query+fileusage-param-prop": "Які властивості отримати:",
index 65e4345..5589c68 100644 (file)
@@ -248,7 +248,7 @@ class ArchivedFile {
                        'fa_minor_mime',
                        'fa_user',
                        'fa_user_text',
-                       'fa_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'fa_actor' : null,
+                       'fa_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'fa_actor' : 'NULL',
                        'fa_timestamp',
                        'fa_deleted',
                        'fa_deleted_timestamp', /* Used by LocalFileRestoreBatch */
index e86f292..7206dce 100644 (file)
@@ -223,7 +223,7 @@ class LocalFile extends File {
                        'img_minor_mime',
                        'img_user',
                        'img_user_text',
-                       'img_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'img_actor' : null,
+                       'img_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'img_actor' : 'NULL',
                        'img_timestamp',
                        'img_sha1',
                ] + MediaWikiServices::getInstance()->getCommentStore()->getFields( 'img_description' );
index aa434d0..b5c44f2 100644 (file)
@@ -138,7 +138,7 @@ class OldLocalFile extends LocalFile {
                        'oi_minor_mime',
                        'oi_user',
                        'oi_user_text',
-                       'oi_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'oi_actor' : null,
+                       'oi_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'oi_actor' : 'NULL',
                        'oi_timestamp',
                        'oi_deleted',
                        'oi_sha1',
index d3aa9f5..fc3d575 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Psr\Log\LoggerInterface;
+
 /**
  * Interface to key-value storage behind an HTTP server.
  *
  * @endcode
  */
 class RESTBagOStuff extends BagOStuff {
+       /**
+        * Default connection timeout in seconds. The kernel retransmits the SYN
+        * packet after 1 second, so 1.2 seconds allows for 1 retransmit without
+        * permanent failure.
+        */
+       const DEFAULT_CONN_TIMEOUT = 1.2;
+
+       /**
+        * Default request timeout
+        */
+       const DEFAULT_REQ_TIMEOUT = 3.0;
 
        /**
         * @var MultiHttpClient
@@ -43,18 +56,34 @@ class RESTBagOStuff extends BagOStuff {
                if ( empty( $params['url'] ) ) {
                        throw new InvalidArgumentException( 'URL parameter is required' );
                }
-               parent::__construct( $params );
                if ( empty( $params['client'] ) ) {
-                       $this->client = new MultiHttpClient( [] );
+                       // Pass through some params to the HTTP client.
+                       $clientParams = [
+                               'connTimeout' => $params['connTimeout'] ?? self::DEFAULT_CONN_TIMEOUT,
+                               'reqTimeout' => $params['reqTimeout'] ?? self::DEFAULT_REQ_TIMEOUT,
+                       ];
+                       foreach ( [ 'caBundlePath', 'proxy' ] as $key ) {
+                               if ( isset( $params[$key] ) ) {
+                                       $clientParams[$key] = $params[$key];
+                               }
+                       }
+                       $this->client = new MultiHttpClient( $clientParams );
                } else {
                        $this->client = $params['client'];
                }
+               // The parent constructor calls setLogger() which sets the logger in $this->client
+               parent::__construct( $params );
                // Make sure URL ends with /
                $this->url = rtrim( $params['url'], '/' ) . '/';
                // Default config, R+W > N; no locks on reads though; writes go straight to state-machine
                $this->attrMap[self::ATTR_SYNCWRITES] = self::QOS_SYNCWRITES_QC;
        }
 
+       public function setLogger( LoggerInterface $logger ) {
+               parent::setLogger( $logger );
+               $this->client->setLogger( $logger );
+       }
+
        /**
         * @param string $key
         * @param int $flags Bitfield of BagOStuff::READ_* constants [optional]
@@ -111,7 +140,7 @@ class RESTBagOStuff extends BagOStuff {
                        'body' => serialize( $value )
                ];
                list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->client->run( $req );
-               if ( $rcode === 200 || $rcode === 201 ) {
+               if ( $rcode === 200 || $rcode === 201 || $rcode === 204 ) {
                        return true;
                }
                return $this->handleError( "Failed to store $key", $rcode, $rerr );
@@ -129,7 +158,7 @@ class RESTBagOStuff extends BagOStuff {
                        'url' => $this->url . rawurlencode( $key ),
                ];
                list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->client->run( $req );
-               if ( $rcode === 200 || $rcode === 204 || $rcode === 205 ) {
+               if ( in_array( $rcode, [ 200, 204, 205, 404, 410 ] ) ) {
                        return true;
                }
                return $this->handleError( "Failed to delete $key", $rcode, $rerr );
index 57e5907..3054156 100644 (file)
@@ -1925,18 +1925,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
        }
 
-       public function tableExists( $table, $fname = __METHOD__ ) {
-               $tableRaw = $this->tableName( $table, 'raw' );
-               if ( isset( $this->sessionTempTables[$tableRaw] ) ) {
-                       return true; // already known to exist
-               }
-
-               $table = $this->tableName( $table );
-               $ignoreErrors = true;
-               $res = $this->query( "SELECT 1 FROM $table LIMIT 1", $fname, $ignoreErrors );
-
-               return (bool)$res;
-       }
+       abstract public function tableExists( $table, $fname = __METHOD__ );
 
        public function indexUnique( $table, $index ) {
                $indexInfo = $this->indexInfo( $table, $index );
index 4b925e6..d86c5ce 100644 (file)
@@ -519,6 +519,19 @@ class DatabaseSqlite extends Database {
                return $this->lastAffectedRowCount;
        }
 
+       function tableExists( $table, $fname = __METHOD__ ) {
+               $tableRaw = $this->tableName( $table, 'raw' );
+               if ( isset( $this->sessionTempTables[$tableRaw] ) ) {
+                       return true; // already known to exist
+               }
+
+               $encTable = $this->addQuotes( $tableRaw );
+               $res = $this->query(
+                       "SELECT 1 FROM sqlite_master WHERE type='table' AND name=$encTable" );
+
+               return $res->numRows() ? true : false;
+       }
+
        /**
         * Returns information about an index
         * Returns false if the index does not exist
index 04a553c..4eaa4e8 100644 (file)
@@ -86,8 +86,6 @@ interface ILoadBalancer {
 
        /** @var int DB handle should have DBO_TRX disabled and the caller will leave it as such */
        const CONN_TRX_AUTOCOMMIT = 1;
-       /** @var int Alias for CONN_TRX_AUTOCOMMIT for b/c; deprecated since 1.31 */
-       const CONN_TRX_AUTO = 1;
 
        /** @var string Manager of ILoadBalancer instances is running post-commit callbacks */
        const STAGE_POSTCOMMIT_CALLBACKS = 'stage-postcommit-callbacks';
index 43f294b..80eb598 100644 (file)
@@ -570,8 +570,7 @@ class ResourceLoader implements LoggerAwareInterface {
        }
 
        /**
-        * Return whether the definition of a module corresponds to a simple ResourceLoaderFileModule
-        * or one of its subclasses.
+        * Whether the module is a ResourceLoaderFileModule (including subclasses).
         *
         * @param string $name Module name
         * @return bool
@@ -584,14 +583,13 @@ class ResourceLoader implements LoggerAwareInterface {
                if ( isset( $info['object'] ) ) {
                        return false;
                }
-               if (
-                       isset( $info['class'] ) &&
-                       $info['class'] !== ResourceLoaderFileModule::class &&
-                       !is_subclass_of( $info['class'], ResourceLoaderFileModule::class )
-               ) {
-                       return false;
-               }
-               return true;
+               return (
+                       // The implied default for 'class' is ResourceLoaderFileModule
+                       !isset( $info['class'] ) ||
+                       // Explicit default
+                       $info['class'] === ResourceLoaderFileModule::class ||
+                       is_subclass_of( $info['class'], ResourceLoaderFileModule::class )
+               );
        }
 
        /**
index 43bd3be..30ac92d 100644 (file)
@@ -21,6 +21,8 @@
  * @ingroup Search
  */
 
+use Wikimedia\Rdbms\IResultWrapper;
+
 /**
  * Search engine hook base class for Mssql (ConText).
  * @ingroup Search
@@ -168,7 +170,7 @@ class SearchMssql extends SearchDatabase {
         * @param int $id
         * @param string $title
         * @param string $text
-        * @return bool|ResultWrapper
+        * @return bool|IResultWrapper
         */
        function update( $id, $title, $text ) {
                // We store the column data as UTF-8 byte order marked binary stream
@@ -191,7 +193,7 @@ class SearchMssql extends SearchDatabase {
         *
         * @param int $id
         * @param string $title
-        * @return bool|ResultWrapper
+        * @return bool|IResultWrapper
         */
        function updateTitle( $id, $title ) {
                $table = $this->db->tableName( 'searchindex' );
index 02ae23d..896e62f 100644 (file)
@@ -24,6 +24,7 @@
 namespace MediaWiki\Session;
 
 use Language;
+use Message;
 
 /**
  * This exists to make IDEs happy, so they don't see the
index b5ced13..f261b72 100644 (file)
@@ -23,6 +23,7 @@
  * @ingroup Pager
  */
 use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\IDatabase;
 use Wikimedia\Rdbms\IResultWrapper;
 use Wikimedia\Rdbms\FakeResultWrapper;
 
index b23afd3..3bf9034 100644 (file)
        "fileexists-thumbnail-yes": "Верагодна, файл зьяўляецца паменшанай копіяй (<em>мініятурай</em>).\n[[$1|thumb]]\nКалі ласка, праверце файл <strong>[[:$1]]</strong>.\nКалі правераны файл зьяўляецца той жа выявай, то загрузка дадатковай мініятуры ня мае сэнсу.",
        "file-thumbnail-no": "Назва файлу пачынаецца з <strong>$1</strong>.\nВерагодна, гэта паменшаная копія выявы (<em>мініятура</em>).\nКалі вы маеце гэтую выяву ў поўным памеры, загрузіце яе, альбо зьмяніце назву файлу.",
        "fileexists-forbidden": "Файл з такой назвай ужо існуе і ня можа быць перапісаны.\nКалі ласка, вярніцеся назад і загрузіце гэты файл з новай назвай. [[File:$1|thumb|center|$1]]",
-       "fileexists-shared-forbidden": "Файл Ð· Ñ\82акой Ð½Ð°Ð·Ð²Ð°Ð¹ Ñ\83жо Ñ\96Ñ\81нÑ\83е Ñ\9e Ð°Ð³Ñ\83лÑ\8cнÑ\8bм Ñ\81Ñ\85овÑ\96Ñ\88Ñ\87Ñ\8b Ñ\84айлаÑ\9e.\nÐ\9aалÑ\96 Ð\92Ñ\8b Ð¶Ð°Ð´Ð°ÐµÑ\86е Ð·Ð°Ð³Ñ\80Ñ\83зÑ\96Ñ\86Ñ\8c Ð\92аÑ\88 Ñ\84айл, Ð²Ñ\8fÑ\80нÑ\96Ñ\86еÑ\81Ñ\8f Ð½Ð°Ð·Ð°Ð´ Ñ\96 Ð·Ð°Ð³Ñ\80Ñ\83зÑ\96Ñ\86е Ð³Ñ\8dÑ\82Ñ\8b Ñ\84айл Ð· Ð½Ð¾Ð²Ð°Ð¹ Ð½Ð°Ð·Ð²Ð°Ð¹. [[File:$1|thumb|center|$1]]",
+       "fileexists-shared-forbidden": "Файл Ð· Ñ\82акой Ð½Ð°Ð·Ð²Ð°Ð¹ Ñ\83жо Ñ\96Ñ\81нÑ\83е Ñ\9e Ð°Ð³Ñ\83лÑ\8cнÑ\8bм Ñ\81Ñ\85овÑ\96Ñ\88Ñ\87Ñ\8b Ñ\84айлаÑ\9e.\nÐ\9aалÑ\96 Ð²Ñ\8b Ð¶Ð°Ð´Ð°ÐµÑ\86е Ð·Ð°Ð³Ñ\80Ñ\83зÑ\96Ñ\86Ñ\8c Ð²Ð°Ñ\88 Ñ\84айл, Ð²Ñ\8fÑ\80нÑ\96Ñ\86еÑ\81Ñ\8f Ð½Ð°Ð·Ð°Ð´ Ñ\96 Ð·Ð°Ð³Ñ\80Ñ\83зÑ\96Ñ\86е Ð³Ñ\8dÑ\82Ñ\8b Ñ\84айл Ð· Ð½Ð¾Ð²Ð°Ð¹ Ð½Ð°Ð·Ð²Ð°Ð¹.\n[[File:$1|thumb|center|$1]]",
        "fileexists-no-change": "Гэтая загрузка зьяўляецца дакладнай копіяй цяперашняй вэрсіі <strong>[[:$1]]</strong>.",
        "fileexists-duplicate-version": "Гэтая загрузка зьяўляецца дакладнай копіяй {{PLURAL:$2|1=старой вэрсіі|старых вэрсіяў}} файлу <strong>[[:$1]]</strong>.",
        "file-exists-duplicate": "Гэты файл дублюе {{PLURAL:$1|1=наступны файл|наступныя файлы}}:",
index 996ba3d..ec13f39 100644 (file)
        "credentialsform-provider": "ДӀаяздарийн тайпа:",
        "credentialsform-account": "Декъашхочун цӀе:",
        "userjsispublic": "Тергам бе: JavaScript бухара агӀонаш чохь къайлаха хаамаш хийла ца беза, уьш массо декъашхойн тӀекхочуш йолу дера.",
-       "usercssispublic": "Тергам бе: CSS бухара агӀонаш чохь къайлаха хаамаш хийла ца беза, уьш массо декъашхойн тӀекхочуш йолу дера."
+       "usercssispublic": "Тергам бе: CSS бухара агӀонаш чохь къайлаха хаамаш хийла ца беза, уьш массо декъашхойн тӀекхочуш йолу дера.",
+       "passwordpolicies": "Паролийн политика",
+       "passwordpolicies-summary": "ХӀокху агӀонгахь гойту декъашхойн паролашна болу бехкам. Декъашхойн юкъабогӀуш болу бакъонийн тобанашка хьажжина бу бехкам.",
+       "passwordpolicies-policy-minimalpasswordlength": "Пароль $1 {{PLURAL:$1|символал}} еха хила еза",
+       "passwordpolicies-policy-passwordcannotmatchusername": "Пароль декъашхочун цӀерах тера хила ца еза",
+       "passwordpolicies-policy-passwordcannotmatchblacklist": "Пароль Ӏаьржачу могӀаман юкъахь йолучарех тера хила ца еза",
+       "passwordpolicies-policy-maximalpasswordlength": "Пароль $1 {{PLURAL:$1|символал}} йоца хила ца еза",
+       "passwordpolicies-policy-passwordcannotbepopular": "Пароль дукха {{PLURAL:$1|лелош йолчарех хила ца еза}}"
 }
index 004c604..6d5ce82 100644 (file)
        "customcssprotected": "Þú hefur ekki leyfi að breyta þessari CSS-umbrotsíðu, því hún hefur notandastillingar annars notanda.",
        "customjsprotected": "Þú hefur ekki leyfi til að breyta þessari JavaScript síðu, því hún hefur notandastillingar annars notanda.",
        "mycustomcssprotected": "Þú hefur ekki leyfi til þess að breyta þessari CSS-síðu.",
+       "mycustomjsonprotected": "Þú hefur ekki heimild til að breyta þessari JSON-síðu.",
        "mycustomjsprotected": "Þú hefur ekki leyfi til þess að breyta þessari JavaScript-síðu.",
        "myprivateinfoprotected": "Þú ert ekki með réttindi til að breyta einkaupplýsingunum þínum.",
        "mypreferencesprotected": "Þú ert ekki með réttindi til að breyta kjörstillingunum þínum.",
        "wrongpasswordempty": "Lykilorðsreiturinn var auður. Reyndu aftur.",
        "passwordtooshort": "Lykilorð skal vera að minnsta kosti $1 {{PLURAL:$1|stafur|stafir}}.",
        "passwordtoolong": "Lykilorð geta ekki verið lengri en $1 {{PLURAL:$1|stafur|stafir}}.",
-       "passwordtoopopular": "Ekki má nota algeng lykilorð. Veldu eitthvað alveg sérstakt lykilorð.",
+       "passwordtoopopular": "Ekki má nota títt valin lykilorð. Vinsamlegast velja lykilorð sem erfiðara er að giska á.",
        "password-name-match": "Þarf að lykilorð þitt sé öðruvísi notandanafni þínu",
        "password-login-forbidden": "Notkun þessa notandanafns og lykilorðs er ekki leyfileg.",
        "mailmypassword": "Endurstilla lykilorð",
        "botpasswords-existing": "Fyrirliggjandi lykilorð vélmenna",
        "botpasswords-createnew": "Búa til nýtt lykilorð vélmennis",
        "botpasswords-editexisting": "Breyta fyrirliggjandi lykilorði vélmennis",
+       "botpasswords-label-needsreset": "(lykilorð þarf að endurstilla)",
        "botpasswords-label-appid": "Heiti vélmennis:",
        "botpasswords-label-create": "Búa til",
        "botpasswords-label-update": "Uppfæra",
        "savechanges": "Vista breytingar",
        "publishpage": "Gefa út síðu",
        "publishchanges": "Gefa út breytingar",
+       "savearticle-start": "Vista síðu…",
+       "savechanges-start": "Vista breytingar…",
+       "publishpage-start": "Birta síðu...",
        "publishchanges-start": "Gefa út breytingar...",
        "preview": "Forskoða",
        "showpreview": "Forskoða",
        "anoneditwarning": "<strong>Viðvörun:</strong> Þú ert ekki innskráð(ur). Vistfang þitt verður sýnt opinberlega ef þú gerir einhverjar breytingar. Ef þú <strong>[$1 skráir þig inn]</strong> eða <strong>[$2 stofnar aðgang]</strong> munu breytingarnar þínar vera tengdar við notandanafn þitt, ásamt öðrum kostum.",
        "anonpreviewwarning": "<em>Þú ert ekki skráð(ur) inn. Vistfang þitt skráist í breytingaskrá síðunnar.</em>",
        "missingsummary": "'''Áminning:''' Þú hefur ekki skrifað breytingarágrip.\nEf þú smellir á Vista aftur, verður breyting þín vistuð án þess.",
+       "selfredirect": "<strong>Viðvörun:</strong> Þú ert að vísa þessa síðu á sjálfa sig.\nÞað kann að vera að þú hafir valið vitlausa marksíðu fyrir tilvísunina eða að þú sért að breyta vitlausri síðu.\nEf þú smellir aftur á „$1“ verður tilvísunin samt búin til.",
        "missingcommenttext": "Gerðu svo vel og skrifaðu athugasemd.",
        "missingcommentheader": "<strong>Áminning:</strong> Þú hefur ekki gefið upp umræðuefni.\nEf þú smellir á \"$1\" aftur, verður breyting þín vistuð án þess.",
        "summary-preview": "Forskoða breytingarágrip:",
        "subject-preview": "Forskoðun viðfangsefnis:",
        "previewerrortext": "Óvænt villa kom upp þegar reynt var að forskoða breytingarnar þínar.",
        "blockedtitle": "Notandi er bannaður",
-       "blockedtext": "'''Notandanafn þitt eða vistfang hefur verið bannað.'''\n\nBannið var sett af $1.\nÁstæðan er eftirfarandi: ''$2''.\n\n* Bannið hófst: $8\n* Banninu lýkur: $6\n* Sá sem banna átti: $7\n\nÞú getur haft samband við $1 eða annan [[{{MediaWiki:Grouppage-sysop}}|stjórnanda]] til að ræða bannið.\nÞú getur ekki notað „Senda þessum notanda tölvupóst“ aðgerðina nema gilt netfang sé skráð í [[Special:Preferences|kjörstillingum þínum]] og að þér hafi ekki verið óheimilað það.\nNúverandi vistfang þitt er $3, og bannnúmerið er #$5.\nHafðu með allar þessar upplýsingar hér fyrir ofan í fyrirspurnum þínum.",
-       "autoblockedtext": "Vistfang þitt hefur verið sjálfvirkt bannað því það var notað af öðrum notanda, sem var bannaður af $1.\nÁstæðan er eftirfarandi:\n\n:''$2''\n\n* Bannið hófst: $8\n* Banninu lýkur: $6\n* Sá sem banna átti: $7\n\nÞú getur haft samband við $1 eða annan [[{{MediaWiki:Grouppage-sysop}}|stjórnanda]] til að ræða bannið.\n\nAthugaðu að þú getur ekki notað „Senda þessum notanda tölvupóst“ aðgerðina nema gilt netfang sé skráð í [[Special:Preferences|kjörstillingum þínum]] og að þér hafi ekki verið óheimilað það.\n\nNúverandi vistfang þitt er $3, og bannnúmerið er #$5.\nHafðu með allar þessar upplýsingar hér fyrir ofan í fyrirspurnum þínum.",
+       "blockedtext": "<strong>Þitt notandanafn eða vistfang hefur verið bannað.</strong>\n\nBannið var sett af $1.\nÁstæðan er eftirfarandi: <em>$2</em>.\n\n* Bannið hófst: $8\n* Banninu lýkur: $6\n* Sá sem banna átti: $7\n\nÞú getur haft samband við $1 eða annan [[{{MediaWiki:Grouppage-sysop}}|stjórnanda]] til að ræða bannið.\nÞú getur ekki notað „Senda þessum notanda tölvupóst“ aðgerðina nema gilt netfang sé skráð í [[Special:Preferences|kjörstillingum þínum]] og að þér hafi ekki verið óheimilað það.\nNúverandi vistfang þitt er $3, og bannnúmerið er #$5.\nHafðu með allar þessar upplýsingar hér fyrir ofan í fyrirspurnum þínum.",
+       "autoblockedtext": "Vistfang þitt hefur verið sjálfvirkt bannað því það var notað af öðrum notanda, sem var bannaður af $1.\nÁstæðan er eftirfarandi:\n\n:<em>$2</em>\n\n* Bannið hófst: $8\n* Banninu lýkur: $6\n* Sá sem banna átti: $7\n\nÞú getur haft samband við $1 eða annan [[{{MediaWiki:Grouppage-sysop}}|stjórnanda]] til að ræða bannið.\n\nAthugaðu að þú getur ekki notað „Senda þessum notanda tölvupóst“ aðgerðina nema gilt netfang sé skráð í [[Special:Preferences|kjörstillingum þínum]] og að þér hafi ekki verið óheimilað það.\n\nNúverandi vistfang þitt er $3, og bannnúmerið er #$5.\nHafðu með allar þessar upplýsingar hér fyrir ofan í fyrirspurnum þínum.",
        "systemblockedtext": "Notandanafnið þitt eða IP-vistfangið hafa verið útilokuð sjálfvirkt af MediaWiki.\nUppgefin ástæða er:\n\n:<em>$2</em>\n\n* Upphaf útilokunar: $8\n* Útilokun rennur út: $6\n* Sá sem átti að útiloka: $7\n\nNúverandi IP-vistfang þitt er$3.\nHafðu allar þessar upplýsingar með í öllum þeim fyrirspurnum sem þú gætir gert vegna þessa.",
        "blockednoreason": "engin ástæða gefin",
        "whitelistedittext": "Þú þarft að $1 þig til að breyta síðum.",
        "blocked-notice-logextract": "Þessi notandi er í banni.\nSíðasta færsla notandans úr bannskrá er birt hér fyrir neðan til skýringar:",
        "clearyourcache": "<strong>Athugaðu:</strong> Eftir vistun kann að vera að þú þurfir að komast hjá skyndiminni vafrans þíns til að sjá breytingarnar.\n* <strong>Firefox / Safari:</strong> Haltu <em>Shift</em> samtímis og þú smellir á <em>Endurhlaða (Reload)</em>, eða ýttu á annaðhvort <em>Ctrl-F5</em> eða <em>Ctrl-R</em> (<em>⌘-R</em> á Mac)\n* <strong>Google Chrome:</strong> Ýttu á <em>Ctrl-Shift-R </em>(<em>⌘-Shift-R</em> á Mac)\n* <strong>Internet Explorer:</strong> Haltu <em>Ctrl</em> samtímis og þú smellir á <em>Endurnýja (Refresh)</em>, eða ýttu á <em>Ctrl-F5</em>\n* <strong>Opera:</strong> Farðu í <em>Verkfæri (Tools) → Stillingar (Preferences)</em> og svo <em>Friðhelgi og öryggi (Privacy & security) → Hreinsa vafragögn (Clear browsing data) → Myndir og skrár í skyndiminni (Chached images and files)</em>",
        "usercssyoucanpreview": "'''Ath:''' Hægt er að nota „{{int:showpreview}}“ hnappinn til að prófa CSS-kóða áður en hann er vistaður.",
+       "userjsonyoucanpreview": "<strong>Ath.:</strong> Hægt er að nota hnappinn „{{int:showpreview}}“ til að prófa JSON-kóða áður en hann er vistaður.",
        "userjsyoucanpreview": "'''Ath:''' Hægt er að nota \"{{int:showpreview}}\" hnappinn til að prófa JavaScript-kóða áður en hann er vistaður.",
        "usercsspreview": "'''Mundu að þú ert aðeins að forskoða CSS-kóðann þinn.'''\n'''Hann hefur ekki enn verið vistaður!'''",
        "userjspreview": "'''Mundu að þú ert aðeins að prófa/forskoða JavaScript-kóðann þinn.'''\n'''Hann hefur ekki enn verið vistaður!'''",
        "apisandbox-dynamic-parameters-add-label": "Bæta við viðfangi:",
        "apisandbox-dynamic-parameters-add-placeholder": "Heiti viðfangs",
        "apisandbox-deprecated-parameters": "Úrelt viðföng",
+       "apisandbox-add-multi": "Bæta við",
        "apisandbox-submit-invalid-fields-title": "Sumir reitir eru ógildir",
        "apisandbox-results": "Niðurstöður",
+       "apisandbox-sending-request": "Sendir API-beiðni...",
        "apisandbox-request-url-label": "Slóð á beiðni:",
        "apisandbox-request-format-json-label": "JSON",
        "apisandbox-request-json-label": "JSON beiðni:",
        "revertpage": "Tók aftur breytingar [[Special:Contributions/$2|$2]] ([[User talk:$2|spjall]]), breytt til síðustu útgáfu [[User:$1|$1]]",
        "revertpage-nouser": "Tók aftur breytingar falins notanda til síðustu útgáfu {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Tók til baka breytingar eftir {{GENDER:$3|$1}};\nsetti yfir á síðustu útgáfu eftir {{GENDER:$4|$2}}.",
+       "rollback-success-notify": "Tók aftur breytingar $1;\nbreytti í síðustu útgafu $2. [$3 Sýna breytingar]",
        "sessionfailure-title": "Mistök í setu",
        "sessionfailure": "Líklega er vandamál með innskráningarsetuna þína;\nhætt hefur verið við þessa aðgerð sem vörn gegn mögulegu samskiptaráni setunar.\nReyndu að senda upplýsingarnar aftur inn.",
+       "changecontentmodel": "Breyta efnislíkani síðu",
+       "changecontentmodel-legend": "Breyta efnislíkani",
        "changecontentmodel-title-label": "Titill síðu",
+       "changecontentmodel-model-label": "Nýtt efnislíkan",
        "changecontentmodel-reason-label": "Ástæða:",
        "changecontentmodel-submit": "Breyta",
+       "changecontentmodel-success-title": "Efnislíkaninu var breytt",
        "logentry-contentmodel-change-revertlink": "taka aftur",
        "logentry-contentmodel-change-revert": "taka aftur",
        "protectlogpage": "Verndunarskrá",
        "unblocked-id": "Bann $1 hefur verið fjarlægt",
        "unblocked-ip": "[[Special:Contributions/$1|$1]] hefur verið afbannaður.",
        "blocklist": "Bannaðir notendur og vistföng",
+       "autoblocklist": "Sjálfvirk bönn",
        "autoblocklist-submit": "Leita",
+       "autoblocklist-legend": "Sýna sjálfvirk bönn",
+       "autoblocklist-total-autoblocks": "Samanlagður fjöldi sjálfvirkra banna: $1",
+       "autoblocklist-empty": "Listinn yfir sjálfvirk bönn er tómur.",
+       "autoblocklist-otherblocks": "{{PLURAL:$1|Annað sjálfvirkt bann|Önnur sjálfvirk bönn}}",
        "ipblocklist": "Bannaðir notendur og vistföng",
        "ipblocklist-legend": "Finna bannaðan notanda",
        "blocklist-userblocks": "Fela notendabönn",
        "tooltip-ca-nstab-help": "Sýna hjálparsíðuna",
        "tooltip-ca-nstab-category": "Sýna efnisflokkasíðuna",
        "tooltip-minoredit": "Merkja þessa breytingu sem minniháttar",
-       "tooltip-save": "Vista breytingarnar",
-       "tooltip-publish": "Gefa út breytingarnar þínar",
+       "tooltip-save": "Vista breytingar þínar",
+       "tooltip-publish": "Gefa út breytingar þínar",
        "tooltip-preview": "Forskoða breytingarnar þínar. Gerðu þetta áður en þú vistar.",
        "tooltip-diff": "Sýna hvaða breytingar þú gerðir á textanum.",
        "tooltip-compareselectedversions": "Sjá breytingarnar á þessari grein á milli útgáfanna sem þú valdir.",
        "version-specialpages": "Kerfissíður",
        "version-parserhooks": "Tengikrókar þáttara (parser hooks)",
        "version-variables": "Breytur",
+       "version-editors": "Ritstjórar",
        "version-antispam": "Varnir gegn amasendingum",
        "version-api": "API",
        "version-other": "Aðrar",
        "tag-mw-new-redirect": "Ný endurbeining",
        "tag-mw-removed-redirect": "Fjarlægði endurbeiningu",
        "tag-mw-replace": "Skipt út",
+       "tag-mw-rollback": "Afturköllun",
        "tag-mw-undo": "Afturkalla",
        "tags-title": "Merki",
        "tags-intro": "Þessi síða sýnir merkin sem hugbúnaðurinn gæti merkt breytingar með, og hvað þau þýða.",
index c1e1ec3..9f7563f 100644 (file)
        "mailmypassword": "ꯄꯥꯁꯋ꯭ꯇ ꯁꯦꯝꯗꯣꯛꯄꯥ",
        "passwordremindertitle": " {{SITENAME}} ꯁꯤꯒꯤ ꯑꯅꯧꯕꯥ ꯉꯥꯏꯍꯥꯛꯀꯤ ꯑꯣꯏꯕꯥ ꯄꯥꯁꯋꯔꯇ",
        "passwordremindertext": "Someone (from IP address $1) requested a new\npassword for {{SITENAME}} ($4). A temporary password for user\n\"$2\" has been created and was set to \"$3\". If this was your\nintent, you will need to log in and choose a new password now.\nYour temporary password will expire in {{PLURAL:$5|one day|$5 days}}.\n\nIf someone else made this request, or if you have remembered your password,\nand you no longer wish to change it, you may ignore this message and\ncontinue using your old password.",
+       "emailconfirmlink": "ꯅꯪꯒꯤ ꯏꯃꯦꯜ ꯑꯦꯗꯔꯦꯁ ꯌꯥꯕꯔꯥ ꯌꯦꯡ ꯎ",
        "accountcreated": "ꯑꯦꯀꯥꯎꯟ ꯁꯥꯈꯔꯦ",
        "loginlanguagelabel": "$1 ꯂꯣꯟ",
        "pt-login": "Chang Sinba",
        "pt-login-button": "Chang Sinba",
+       "pt-login-continue-button": "ꯂꯣꯘ ꯏꯟ ꯃꯈꯥ ꯆꯠꯊꯧ",
        "pt-createaccount": "ꯑꯩꯒꯤ ꯑꯣꯏꯕꯥ ꯑꯃꯥ ꯁꯦꯝꯕꯥ",
        "pt-userlogout": "Log out",
        "oldpassword": "ꯑꯔꯤꯕꯥ ꯄꯥꯁꯋꯔꯇ",
        "botpasswords": "ꯕꯣꯇ ꯄꯥꯁꯋꯔꯇ",
        "botpasswords-summary": "<em>Bot passwords</em> allow access to a user account via the API without using the account's main login credentials. The user rights available when logged in with a bot password may be restricted.\n\nIf you don't know why you might want to do this, you should probably not do it. No one should ever ask you to generate one of these and give it to them.",
        "botpasswords-disabled": "ꯕꯣꯇ ꯄꯥꯁꯋꯔꯇ ꯌꯥꯉꯟꯗꯕꯥ",
+       "botpasswords-label-create": "ꯁꯥꯕꯥ",
+       "botpasswords-label-update": "ꯅꯧꯊꯣꯛꯍꯟꯕꯥ",
+       "botpasswords-label-cancel": "ꯀꯛꯊꯠꯄꯥ",
+       "botpasswords-label-delete": "ꯃꯥꯡꯍꯟꯕꯥ",
+       "botpasswords-label-resetpassword": "ꯄꯥꯁꯋ꯭ꯇ ꯑꯃꯨꯛ ꯍꯟꯅꯥ ꯁꯦꯝꯗꯣꯛꯄꯥ",
+       "botpasswords-label-grants": "ꯆꯥꯟꯅꯕꯥ ꯌꯥꯕꯥ ꯑꯌꯥꯕ",
+       "botpasswords-help-grants": "Grants allow access to rights already held by your user account. Enabling a grant here does not provide access to any rights that your user account would not otherwise have. See the [[Special:ListGrants|table of grants]] for more information.",
+       "botpasswords-created-title": "ꯕꯣꯠ ꯄꯥꯁꯋ꯭ꯔꯇ ꯁꯥꯈꯔꯦ",
+       "botpasswords-deleted-title": "ꯕꯣꯠ ꯄꯥꯁꯋ꯭ꯔꯇ ꯀꯛꯊꯠꯈꯔꯦ",
+       "resetpass_forbidden": "ꯄꯥꯁꯋ꯭ꯔꯇ ꯍꯣꯡꯗꯣꯧꯄꯥ ꯌꯥꯔꯣꯏ",
+       "resetpass_forbidden-reason": "$1 ꯄꯥꯁꯋ꯭ꯔꯇ ꯍꯣꯡꯗꯣꯧꯄꯥ ꯌꯥꯔꯣꯏ",
+       "resetpass-no-info": "ꯃꯁꯤꯒꯤ ꯂꯥꯃꯥꯏꯁꯤ ꯍꯦꯧꯇꯥ ꯌꯧꯅꯕꯥ ꯅꯪ ꯁꯣꯏꯗꯅꯥ ꯂꯣꯒ ꯏꯟ ꯇꯧꯒꯗꯕꯅꯤ",
+       "resetpass-submit-loggedin": "ꯄꯥꯁꯋ꯭ꯔꯇ ꯍꯣꯡꯗꯣꯛꯄꯥ",
+       "resetpass-submit-cancel": "ꯀꯛꯊꯠꯄꯥ",
+       "resetpass-wrong-oldpass": "ꯃꯇꯝ ꯈꯔꯥꯒꯤ ꯑꯣꯏꯅꯥ ꯀꯔꯤꯝꯇꯥ ꯌꯥꯎꯗꯦ  ꯅꯠꯇꯔꯒꯥ ꯍꯧꯖꯤꯧꯀꯤ ꯄꯥꯁꯋ꯭ꯔꯇ꯫\nꯅꯪꯅꯥ ꯄꯥꯁꯋꯑꯔꯇ ꯍꯥꯟꯅꯗꯒꯤ ꯍꯣꯡꯂꯝꯂꯅꯤ ꯅꯠꯇꯔꯒꯥ ꯍꯪꯒꯠꯂꯨ ꯉꯥꯏꯍꯥꯛꯀꯤ ꯑꯣꯏꯕꯥ ꯄꯥꯁꯋ꯭ꯔꯇ",
+       "resetpass-temp-password": "ꯉꯩꯍꯥꯛꯀꯤ ꯑꯣꯏꯕꯥ ꯄꯥꯁꯋ꯭ꯔꯇ",
        "passwordreset": "ꯄꯥꯁꯋ꯭ꯇ ꯁꯦꯝꯗꯣꯛꯄꯥ",
+       "passwordreset-username": "ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯥ ꯃꯃꯤꯡ",
+       "passwordreset-domain": "ꯗꯣꯃꯦꯟ",
+       "passwordreset-email": "ꯏꯃꯦꯜ ꯂꯥꯐꯝ",
+       "passwordreset-emailtitle": "{{SITENAME}} ꯑꯀꯨꯞꯄꯥ ꯃꯔꯣꯜ",
+       "passwordreset-emailtext-ip": "Someone (probably you, from IP address $1) requested a reset of your\npassword for {{SITENAME}} ($4). The following user {{PLURAL:$3|account is|accounts are}}\nassociated with this email address:\n\n$2\n\n{{PLURAL:$3|This temporary password|These temporary passwords}} will expire in {{PLURAL:$5|one day|$5 days}}.\nYou should log in and choose a new password now. If someone else made this\nrequest, or if you have remembered your original password, and you no longer\nwish to change it, you may ignore this message and continue using your old\npassword.",
+       "passwordreset-emailtext-user": "User $1 on {{SITENAME}} requested a reset of your password for {{SITENAME}}\n($4). The following user {{PLURAL:$3|account is|accounts are}} associated with this email address:\n\n$2\n\n{{PLURAL:$3|This temporary password|These temporary passwords}} will expire in {{PLURAL:$5|one day|$5 days}}.\nYou should log in and choose a new password now. If someone else made this\nrequest, or if you have remembered your original password, and you no longer\nwish to change it, you may ignore this message and continue using your old\npassword.",
+       "passwordreset-emailelement": "$1 ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯥ\n$2 ꯉꯩꯍꯥꯛꯀꯤ ꯑꯣꯏꯕꯥ ꯄꯥꯁꯋꯔꯇ",
+       "changeemail-none": "ꯑꯃꯥꯇꯥ ꯅꯠꯇꯦ",
+       "changeemail-password": "ꯅꯪꯒꯤ {{SITENAME}} ꯄꯥꯁꯋ꯭ꯔꯇ:",
+       "changeemail-submit": "ꯏ-ꯃꯦꯜ ꯍꯣꯡꯕꯥ",
        "bold_sample": "ꯆꯥꯎꯅꯥ ꯏꯕꯥ",
        "bold_tip": "ꯆꯥꯎꯅꯥ ꯏꯕꯥ",
        "italic_sample": "ꯋꯥꯔꯦꯡ ꯐꯆꯅꯥ ꯏꯕꯥ",
        "sig_tip": "ꯃꯇꯝꯒꯤ ꯏꯁꯇꯥꯝꯒꯥ ꯂꯣꯏꯟꯅꯥ ꯅꯪꯒꯤ ꯈꯨꯇꯌꯦꯛ",
        "hr_tip": "ꯐꯩꯅꯥ ꯆꯤꯡꯕꯥ ꯂꯥ ꯏ (ꯃꯔꯤꯛ ꯃꯔꯤꯛ ꯑꯣꯏꯅꯥ ꯁꯤꯖꯤꯟꯅꯧ)",
        "summary": "ꯑꯇꯦꯟꯕꯥ ꯁꯟꯗꯣꯛꯅꯥ ꯇꯥꯛꯄꯥ",
+       "subject": "ꯍꯤꯔꯝ",
        "minoredit": "ꯃꯁꯤ ꯑꯄꯤꯛꯄꯥ ꯁꯦꯝꯒꯠꯄꯅꯤ",
        "watchthis": "ꯃꯁꯤꯒꯤ ꯂꯥꯃꯥꯏꯁꯤ ꯌꯦꯡꯉꯨ",
        "savearticle": "ꯂꯥꯃꯥꯏ ꯇꯨꯪꯁꯤꯟꯕꯥ",
+       "savechanges": "ꯑꯍꯣꯡꯕꯗꯨ ꯇꯨꯪꯁꯤꯟꯂꯨ",
+       "publishpage": "ꯂꯥꯃꯥꯏ ꯐꯣꯡꯗꯣꯛ ꯎ",
+       "publishchanges": "ꯑꯍꯣꯡꯕꯁꯤꯡꯗꯨ ꯐꯣꯡꯗꯣꯛ ꯎ",
+       "savearticle-start": "ꯂꯥꯃꯥꯏ ꯁꯤ ꯇꯨꯡꯁꯤꯜꯂꯨ",
+       "savechanges-start": "ꯑꯍꯣꯡꯕꯁꯤꯡꯗꯨ ꯇꯨꯪꯁꯤꯟꯂꯨ",
+       "publishpage-start": "ꯂꯥꯃꯥꯏ ꯐꯣꯡꯗꯣꯛ ꯎ",
+       "publishchanges-start": "ꯑꯍꯣꯡꯕꯁꯤꯡꯗꯨ ꯐꯣꯡꯗꯣꯛ ꯎ",
+       "preview": "ꯃꯥꯃꯥꯡꯒꯤ",
        "showpreview": "ꯍꯥꯟꯅꯒꯤꯗꯨ ꯎꯨꯇꯂꯨ",
        "showdiff": "ꯑꯍꯣꯡꯕꯗꯨ ꯎꯨꯇꯂꯨ",
+       "blankarticle": "<strong>Warning:</strong> The page you are creating is blank.\nIf you click \"$1\" again, the page will be created without any content.",
        "anoneditwarning": "<strong>Warning:</strong> You are not logged in. Your IP address will be publicly visible if you make any edits. If you <strong>[$1 log in]</strong> or <strong>[$2 create an account]</strong>, your edits will be attributed to your username, along with other benefits.",
        "loginreqlink": "Chang Sinba",
+       "newarticle": "ꯑꯅꯧꯕꯥ",
        "newarticletext": "You have followed a link to a page that does not exist yet.\nTo create the page, start typing in the box below (see the [$1 help page] for more info).\nIf you are here by mistake, click your browser's <strong>back</strong> button.",
+       "anontalkpagetext": "----\n<em>This is the discussion page for an anonymous user who has not created an account yet, or who does not use it.</em>\nWe therefore have to use the numerical IP address to identify him/her.\nSuch an IP address can be shared by several users.\nIf you are an anonymous user and feel that irrelevant comments have been directed at you, please [[Special:CreateAccount|create an account]] or [[Special:UserLogin|log in]] to avoid future confusion with other anonymous users.",
        "noarticletext": "There is currently no text in this page.\nYou can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} create this page]</span>.",
        "noarticletext-nopermission": "There is currently no text in this page.\nYou can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages, or <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span>, but you do not have permission to create this page.",
+       "missing-revision": "The revision #$1 of the page named \"{{FULLPAGENAME}}\" does not exist.\n\nThis is usually caused by following an outdated history link to a page that has been deleted.\nDetails can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
+       "continue-editing": "ꯁꯦꯝꯒꯠꯄꯒꯤ ꯃꯐꯝꯗꯨꯗꯥ ꯆꯠꯂꯨ",
        "editing": "$1 ꯁꯦꯝꯒꯠꯂꯤ",
        "creating": "Creating $1",
        "editingsection": "Editing $1 (section)",
index c3fc175..e73006f 100644 (file)
        "rev-deleted-user": "(အသုံးပြုသူအမည် ဖယ်ရှားပြီး)",
        "rev-deleted-event": "(အသေးစိတ် မှတ်တမ်း ဖယ်ရှားပြီးပြီ)",
        "rev-deleted-text-permission": "ဤစာမျက်နှာ ရာဇဝင်များသည် <strong>ဖျက်ထားပြီး</strong>ဖြစ်သည်။\nအသေးစိတ်များကို [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ဖျက်ထားသည့် မှတ်တမ်း]တွင် တွေ့ရှိနိုင်ပါသည်။",
+       "rev-deleted-unhide-diff": "ဤမူကွဲ၏ တည်းဖြတ်မူတစ်ခုအား <strong>ဖျက်ထားသည်</strong>။\nအသေးစိတ်ကို [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ဖျက်ထားသည့် မှတ်တမ်း]တွင် တွေ့ရှိနိုင်သည်။\nသင့်အနေဖြင့် ဆန္ဒရှိပါက [$1 ဤမူကွဲ]ကို ဆက်လက် ကြည့်ရှုနိုင်သည်။",
+       "rev-deleted-diff-view": "ဤမူကွဲ၏ တည်းဖြတ်မူတစ်ခုအား <strong>ဖျက်ထားသည်</strong>။\nဤမူကွဲကို ကြည့်ရှုနိုင်ပြီး အသေးစိတ်ကို [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ဖျက်ထားသည့် မှတ်တမ်း]တွင် တွေ့ရှိနိုင်သည်။",
        "rev-delundel": "အမြင်ပုံစံ ပြောင်းလဲရန်",
        "rev-showdeleted": "ပြ",
        "revisiondelete": "မူများကို ဖျက်ရန်/မဖျက်တော့ရန်",
index 36c2328..7e9583f 100644 (file)
        "mostinterwikis": "Páginas com mais hiperligações interwikis",
        "mostrevisions": "Páginas com mais revisões",
        "prefixindex": "Todas as páginas iniciadas por",
-       "prefixindex-namespace": "Todas as páginas com prefixo (domínio $1)",
+       "prefixindex-namespace": "Todas as páginas com prefixo (espaço nominal $1)",
        "prefixindex-submit": "Mostrar",
        "prefixindex-strip": "Remover prefixo",
        "shortpages": "Páginas curtas",
index aa135f8..3d12f42 100644 (file)
        "talk": "ᱜᱟᱞᱢᱟᱨᱟᱣ",
        "views": "ᱧᱮᱞᱚᱜᱚᱜ",
        "toolbox": "ᱦᱟᱹᱛᱭᱟᱹᱨ",
+       "tool-link-userrights": "{{GENDER:$1|ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}} ᱜᱟᱫᱮᱞ ᱵᱚᱫᱚᱞ",
+       "tool-link-userrights-readonly": "{{GENDER:$1|ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}} ᱜᱟᱫᱮᱞ ᱧᱮᱞ",
        "tool-link-emailuser": "ᱤᱢᱮᱞᱟᱭᱢᱮ ᱱᱩᱭ {{GENDER:$1|ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}}",
        "imagepage": "ᱨᱮᱫ ᱥᱟᱦᱴᱟ ᱧᱮᱞᱢᱮ",
        "mediawikipage": "ᱠᱷᱚᱵᱚᱨ ᱥᱟᱦᱴᱟ ᱧᱮᱞᱢᱮ",
        "jumptonavigation": "ᱟᱹᱪᱩᱨᱵᱟᱲᱟ",
        "jumptosearch": "ᱥᱮᱸᱫᱽᱨᱟ",
        "view-pool-error": "Ikạkańmẽ, sarvarre nitoḱ do aḍi cap menaḱa.\nẠḍi aema beoharko noa sakam ńel lạgit́ko kurumuṭueda.\nNãwate noa sakam ńel kurumuṭuy lạgit́te dayakate mit́ghạṛi tạṅgiymẽ.\n$1",
+       "generic-pool-error": "ᱤᱠᱟᱹᱠᱟᱹᱧᱢᱮ, ᱱᱚᱶᱟ ᱥᱚᱨᱵᱷᱚᱨ ᱨᱮ ᱱᱤᱛ ᱟᱹᱰᱤᱜᱟᱱ ᱪᱟᱯ ᱢᱮᱱᱟᱜᱼᱟ ᱾\nᱟᱹᱰᱤ ᱟᱭᱢᱟ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱱᱚᱶᱟ ᱥᱟᱠᱟᱢ ᱧᱮᱞ ᱞᱟᱹᱜᱤᱫ ᱠᱚ ᱨᱤᱠᱟᱹᱭᱮᱫᱼᱟ ᱾\nᱱᱚᱶᱟ ᱥᱟᱠᱟᱢ ᱧᱮᱞ ᱞᱟᱹᱜᱤᱰ ᱱᱟᱥᱮ ᱛᱟᱺᱜᱤ ᱢᱮ ᱾",
        "pool-timeout": "Somoy paromena cạbi lạgit́te tạṅgi hoyoḱkana",
        "pool-queuefull": "Pool queue is full",
        "pool-errorunknown": "ᱵᱟᱝ ᱵᱟᱰᱟᱭ ᱦᱩᱲᱟᱹᱜ",
        "filerenameerror": "\"$1\" ᱨᱮᱫ ᱨᱮᱭᱟᱜ ᱧᱩᱛᱩᱢ ᱵᱚᱫᱚᱞ ᱠᱟᱛᱮ \"$2\" ᱮᱢ ᱵᱟᱝ ᱜᱟᱱᱚᱜ ᱠᱟᱱᱟ᱾",
        "filedeleteerror": "$1 ᱨᱮᱫ ᱫᱚ ᱵᱟᱝ ᱜᱮᱫᱽ ᱜᱤᱰᱤ ᱞᱮᱱᱟ",
        "directorycreateerror": "\"$1\" ᱰᱟᱭᱨᱮᱠᱴᱳᱨᱤ ᱫᱚ ᱵᱟᱝ ᱛᱮᱭᱟᱨᱞᱮᱱᱟ᱾",
+       "directorynotreadableerror": "ᱯᱟᱠᱷᱟ \"$1\" ᱫᱚ ᱯᱟᱲᱦᱟᱣ ᱵᱟᱭ ᱜᱟᱱᱚᱜᱼᱟ ᱾",
        "filenotfound": "\"$1\" ᱨᱮᱫ ᱫᱚ ᱵᱟᱝ ᱧᱟᱢᱞᱮᱱᱟ᱾",
        "unexpected": "ᱵᱟᱝ ᱟᱥᱟᱜ ᱠᱟᱱ ᱢᱟᱹᱱ: \"$1\"=\"$2\".",
        "formerror": "ᱦᱩᱲᱟᱹᱜ: ᱯᱷᱚᱨᱚᱢ ᱫᱚ ᱵᱟᱝ ᱡᱤᱢᱟᱹᱞᱮᱱᱟ᱾",
index 3c3e629..472dcc5 100644 (file)
        "dellogpage": "Дневник брисања",
        "dellogpagetext": "Испод је списак последњих брисања.",
        "deletionlog": "дневник брисања",
+       "logentry-create-create": "$1 {{GENDER:$2|креирао је|креирала је}} страницу $3",
        "reverted": "Враћено на ранију измену",
        "deletecomment": "Разлог:",
        "deleteotherreason": "Други/додатни разлог:",
index b1c1bc3..ecc23b6 100644 (file)
        "dellogpage": "Dnevnik brisanja",
        "dellogpagetext": "Ispod je spisak poslednjih brisanja.",
        "deletionlog": "dnevnik brisanja",
+       "logentry-create-create": "$1 {{GENDER:$2|kreirao je|kreirala je}} stranicu $3",
        "reverted": "Vraćeno na raniju izmenu",
        "deletecomment": "Razlog:",
        "deleteotherreason": "Drugi/dodatni razlog:",
index 2bf9d8c..4dce507 100644 (file)
@@ -76,7 +76,8 @@
                        "Avatar6",
                        "Fitoschido",
                        "Movses",
-                       "Esk78"
+                       "Esk78",
+                       "Vlad5250"
                ]
        },
        "tog-underline": "Підкреслювання посилань:",
        "right-browsearchive": "пошук вилучених сторінок",
        "right-undelete": "відновлення сторінок",
        "right-suppressrevision": "перегляд, приховування та відновлення конкретних змін сторінок від будь-якого користувача",
-       "right-viewsuppressed": "Ð\9fеÑ\80еглÑ\8fд Ð·Ð¼Ñ\96н, Ð¿Ñ\80иÑ\85оваих від усіх користувачів",
+       "right-viewsuppressed": "пеÑ\80еглÑ\8fд Ð·Ð¼Ñ\96н, Ð¿Ñ\80иÑ\85ованих від усіх користувачів",
        "right-suppressionlog": "перегляд приватних журналів",
        "right-block": "заборона редагувань для інших дописувачів",
        "right-blockemail": "блокування користувача від надсилання електронної пошти",
        "right-protect": "зміна рівнів захисту та редагування каскадно захищених сторінок",
        "right-editprotected": "редагування сторінок з рівнем захисту «{{int:protect-level-sysop}}»",
        "right-editsemiprotected": "редагування сторінок з рівнем захисту «{{int:protect-level-autoconfirmed}}»",
-       "right-editcontentmodel": "Редагувати модель вмісту сторінки",
+       "right-editcontentmodel": "редагування моделі вмісту сторінки",
        "right-editinterface": "редагування інтерфейсу користувача",
        "right-editusercss": "редагування CSS-файлів інших користувачів",
        "right-edituserjson": "редагування JSON-файлів інших користувачів",
        "action-viewmywatchlist": "перегляд власного списку спостереження",
        "action-viewmyprivateinfo": "перегляд своєї приватної інформації",
        "action-editmyprivateinfo": "редагування своєї приватної інформації",
-       "action-editcontentmodel": "редагувати модель вмісту сторінки",
+       "action-editcontentmodel": "редагування моделі вмісту сторінки",
        "action-managechangetags": "створення та (де)активування міток",
        "action-applychangetags": "додавання міток разом зі змінами",
        "action-changetags": "додавання або вилучення будь-яких міток для певних версій сторінок або записів журналів",
index f7909c0..57bce5c 100644 (file)
        "prefs-dateformat": "تاریخ کی ترتیب",
        "prefs-timeoffset": "وقت کی ترتیب",
        "prefs-advancedediting": "اعلی اختیارات",
+       "prefs-developertools": "آلات ترقی دہندہ",
        "prefs-editor": "خانہ ترمیم",
        "prefs-preview": "نمائش",
        "prefs-advancedrc": "اضافی اختیارات",
index 271cbf3..7f36442 100644 (file)
@@ -24,6 +24,7 @@
 
 use MediaWiki\Logger\LegacyLogger;
 use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\IDatabase;
 
 $optionsWithArgs = RecompressTracked::getOptionsWithArgs();
 require __DIR__ . '/../commandLine.inc';
@@ -640,7 +641,7 @@ class RecompressTracked {
        /**
         * Gets a DB master connection for the given external cluster name
         * @param string $cluster
-        * @return Database
+        * @return IDatabase
         */
        function getExtDB( $cluster ) {
                $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
index 2bbeabf..2340f9c 100644 (file)
@@ -26,8 +26,8 @@
         * @cfg {boolean} [showMissing=true] Show missing pages
         * @cfg {boolean} [addQueryInput=true] Add exact user's input query to results
         * @cfg {boolean} [excludeCurrentPage] Exclude the current page from suggestions
-        * @cfg {boolean} [validateTitle=true] Whether the input must be a valid title (if set to true,
-        *  the widget will marks itself red for invalid inputs, including an empty query).
+        * @cfg {boolean} [validateTitle=true] Whether the input must be a valid title
+        * @cfg {boolean} [required=false] Whether the input must not be empty
         * @cfg {Object} [cache] Result cache which implements a 'set' method, taking keyed values as an argument
         * @cfg {mw.Api} [api] API object to use, creates a default mw.Api instance if not specified
         */
         * @return {boolean} The query is valid
         */
        mw.widgets.TitleWidget.prototype.isQueryValid = function () {
-               return this.validateTitle ? !!this.getMWTitle() : true;
+               if ( !this.validateTitle ) {
+                       return true;
+               }
+               if ( !this.required && this.getQueryValue() === '' ) {
+                       return true;
+               }
+               return !!this.getMWTitle();
        };
 
 }( jQuery, mediaWiki ) );
index 0fae63a..0b12c84 100644 (file)
@@ -2272,6 +2272,83 @@ hi
 <link rel="mw:PageProp/Category" href="./Category:Ho" />
 !! end
 
+!! test
+Paragraph wrapping following unclosed table
+!! options
+parsoid=wt2html,html2html
+!! wikitext
+{|
+|-
+
+{|
+| x
+|}
+
+a
+
+b
+
+c
+!! html/php+tidy
+<table>
+
+
+</table><table>
+<tbody><tr>
+<td>x
+</td></tr></tbody></table>
+<p>a
+</p><p>b
+</p><p>c
+</p>
+!! html/parsoid
+<table data-parsoid='{"autoInsertedEnd":true}'>
+<tbody><tr class="mw-empty-elt" data-parsoid='{"startTagSrc":"|-"}'></tr>
+
+</tbody></table><table>
+<tbody><tr data-parsoid='{"autoInsertedStart":true}'><td>x</td></tr>
+</tbody></table>
+
+<p>a</p>
+
+<p>b</p>
+
+<p>c</p>
+!! end
+
+!! test
+Paragraph wrapping suppressed in html p
+!! options
+parsoid=wt2html,html2html
+!! wikitext
+<p>
+
+
+hi
+
+
+
+</p>
+!! html/php+tidy
+<p>
+
+
+hi
+
+
+
+</p>
+!! html/parsoid
+<p data-parsoid='{"stx":"html"}'>
+
+
+hi
+
+
+
+</p>
+!! end
+
 ###
 ### Preformatted text
 ###
 a
 <table></table>
 !! html/parsoid
-<p data-parsoid='{"fostered":true,"autoInsertedEnd":true}'>a</p><table>
-<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
-
-</tr></tbody></table>
+<span data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true}'>
+a
+</span><table>
+<tbody><tr class="mw-empty-elt" data-parsoid='{"startTagSrc":"|-"}'></tr></tbody></table>
 !! end
 
 !! test
@@ -12786,16 +12863,22 @@ Templates: Block Tags: 2. Back-to-back template uses
 
 !!end
 
-# This is an edge case relating to paragraph wrapping.
-!!test
+## This is an edge case relating to paragraph wrapping.
+## Note that Parsoid fails to match Remex because it's using the closing tag
+## as a heuristic to determine if it's in a block, rather than SAX based events.
+!! test
 Templates: Correctly encapsulate templates producing </p> tag without a corresponding <p> tag
 !! wikitext
 {{echo|a
 b</p>}}
+!! html/php+tidy
+<p>a
+</p><p>
+b</p><p class="mw-empty-elt"></p>
 !! html/parsoid
-<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\nb&lt;/p>"}},"i":0}}]}'>a
-b</p>
-!!end
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\nb&lt;/p>"}},"i":0}}]}'>a</p><span about="#mwt1">
+</span><span about="#mwt1">b</span><p about="#mwt1" data-parsoid='{"autoInsertedStart":true,"stx":"html"}'></p>
+!! end
 
 !!test
 Templates: Links: 1. Simple example
@@ -13164,13 +13247,13 @@ parsoid=wt2html,wt2wt
 <link rel="mw:PageProp/Category" href="./Category:Bar1"><link rel="mw:PageProp/Category" href="./Category:Bar2"><table><tbody><tr><td>foo</td></tr></tbody></table>
 !!end
 
-!!test
+!! test
 Templates: Wiki Tables: 1a. Fostering of entire template content
 !! wikitext
 {|
 {{echo|a}}
 |}
-!! html
+!! html/php
 <table>
 a
 <tr><td></td></tr></table>
 a
 <table><tbody><tr><td></td></tr></tbody></table>
 !! html/parsoid
-<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}},"\n|}"]}'>a</p><table about="#mwt2">
+<span about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}},"\n|}"]}'>a</span><table about="#mwt2">
 
 </table>
 !! end
@@ -13216,14 +13299,14 @@ foo
 </table>
 !! end
 
-!!test
+!! test
 Templates: Wiki Tables: 2. Fostering of partial template content
 !! wikitext
 {|
 {{echo|a
 <div>b</div>}}
 |}
-!! html
+!! html/php
 <table>
 a
 <div>b</div>
 <div>b</div><table>
 <tbody><tr><td></td></tr></tbody></table>
 !! html/parsoid
-<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n&lt;div>b&lt;/div>"}},"i":0}},"\n|}"]}'>a</p><div about="#mwt2">b</div><table about="#mwt2">
+<span about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n&lt;div>b&lt;/div>"}},"i":0}},"\n|}"]}'>a</span><div about="#mwt2">b</div><table about="#mwt2">
 
 
 </table>
@@ -23415,7 +23498,12 @@ Line two
 
 !! end
 
-# FIXME: Why does/should the blockquote+div combo suppress p-wrapping here?
+## This is a corner case interaction between the paragraph wrapping in the
+## php parser's BlockLevelPass and Remex.  `doBlockLevels` has a notion of
+## some tags which close paragraphs (and thus prevent wrapping on their line),
+## of which "div" is one, but do p-wrapping inside them.  These are referred
+## to as "never suppressing".  Remex, for its part, doesn't traverse into
+## "div"s to p-wrap.  Hence, we only get this partial wrapping.
 !! test
 Paragraphs inside blockquotes/divs (no extra line breaks)
 !! wikitext
index cf48215..41368ce 100644 (file)
@@ -315,6 +315,8 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
                        'SiteStore' => [ 'SiteStore', SiteStore::class ],
                        'SiteLookup' => [ 'SiteLookup', SiteLookup::class ],
                        'StatsdDataFactory' => [ 'StatsdDataFactory', IBufferingStatsdDataFactory::class ],
+                       'PerDbNameStatsdDataFactory' =>
+                               [ 'PerDbNameStatsdDataFactory', IBufferingStatsdDataFactory::class ],
                        'InterwikiLookup' => [ 'InterwikiLookup', InterwikiLookup::class ],
                        'EventRelayerGroup' => [ 'EventRelayerGroup', EventRelayerGroup::class ],
                        'SearchEngineFactory' => [ 'SearchEngineFactory', SearchEngineFactory::class ],
index cf605c1..d6b43e5 100644 (file)
@@ -190,32 +190,38 @@ class LoadBalancerTest extends MediaWikiTestCase {
 
        private function assertWriteAllowed( Database $db ) {
                $table = $db->tableName( 'some_table' );
+               // Trigger a transaction so that rollback() will remove all the tables.
+               // Don't do this for MySQL/Oracle as they auto-commit transactions for DDL
+               // statements such as CREATE TABLE.
+               $useAtomicSection = in_array( $db->getType(), [ 'sqlite', 'postgres', 'mssql' ], true );
                try {
                        $db->dropTable( 'some_table' ); // clear for sanity
+                       $this->assertNotEquals( $db::STATUS_TRX_ERROR, $db->trxStatus() );
 
-                       // Trigger DBO_TRX to create a transaction so the flush below will
-                       // roll everything here back in sqlite. But don't actually do the
-                       // code below inside an atomic section becaue MySQL and Oracle
-                       // auto-commit transactions for DDL statements like CREATE TABLE.
-                       $db->startAtomic( __METHOD__ );
-                       $db->endAtomic( __METHOD__ );
-
+                       if ( $useAtomicSection ) {
+                               $db->startAtomic( __METHOD__ );
+                       }
                        // Use only basic SQL and trivial types for these queries for compatibility
                        $this->assertNotSame(
                                false,
                                $db->query( "CREATE TABLE $table (id INT, time INT)", __METHOD__ ),
                                "table created"
                        );
+                       $this->assertNotEquals( $db::STATUS_TRX_ERROR, $db->trxStatus() );
                        $this->assertNotSame(
                                false,
                                $db->query( "DELETE FROM $table WHERE id=57634126", __METHOD__ ),
                                "delete query"
                        );
+                       $this->assertNotEquals( $db::STATUS_TRX_ERROR, $db->trxStatus() );
                } finally {
-                       // Drop the table to clean up, ignoring any error.
-                       $db->query( "DROP TABLE $table", __METHOD__, true );
-                       // Rollback the DBO_TRX transaction for sqlite's benefit.
+                       if ( !$useAtomicSection ) {
+                               // Drop the table to clean up, ignoring any error.
+                               $db->dropTable( 'some_table' );
+                       }
+                       // Rollback the atomic section for sqlite's benefit.
                        $db->rollback( __METHOD__, 'flush' );
+                       $this->assertNotEquals( $db::STATUS_TRX_ERROR, $db->trxStatus() );
                }
        }
 
index c12882b..8f4aae3 100644 (file)
@@ -440,6 +440,7 @@ class DatabaseTest extends PHPUnit\Framework\TestCase {
                        'numFields', 'numRows',
                        'open',
                        'strencode',
+                       'tableExists'
                ];
                $db = $this->getMockBuilder( Database::class )
                        ->disableOriginalConstructor()