Merge "Special:Preferences: Construct fake tabs to avoid FOUC"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 18 May 2018 18:44:01 +0000 (18:44 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 18 May 2018 18:44:01 +0000 (18:44 +0000)
15 files changed:
RELEASE-NOTES-1.32
autoload.php
includes/OutputPage.php
includes/collation/Collation.php
includes/collation/CollationFa.php [deleted file]
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderClientHtml.php
includes/specials/SpecialTrackingCategories.php
includes/specials/SpecialWhatlinkshere.php
includes/specials/pagers/UsersPager.php
languages/data/Names.php
languages/i18n/en.json
languages/i18n/qqq.json
tests/phpunit/includes/collation/CollationFaTest.php [deleted file]
tests/phpunit/includes/resourceloader/ResourceLoaderClientHtmlTest.php

index 4663751..62e3df8 100644 (file)
@@ -26,6 +26,8 @@ production.
 * (T112474) Generalized the ResourceLoader mechanism for overriding modules
   using a particular page during edit previews.
 * Added 'ApiParseMakeOutputPage' hook.
+* (T174313) Added checkbox on Special:ListUsers to display only users in temporary
+  user groups.
 
 === External library changes in 1.32 ===
 * …
@@ -109,6 +111,7 @@ because of Phabricator reports.
 * Overriding SearchEngine::{searchText,searchTitle,searchArchiveTitle}
   in extending classes is deprecated.  Extend related doSearch* methods
   instead.
+* CollationFa has been removed completely as it's not needed anymore
 
 === Other changes in 1.32 ===
 * Soft hyphens (U+00AD) are now automatically removed from titles; these
index c55b931..9e876db 100644 (file)
@@ -280,7 +280,6 @@ $wgAutoloadLocalClasses = [
        'Collation' => __DIR__ . '/includes/collation/Collation.php',
        'CollationCkb' => __DIR__ . '/includes/collation/CollationCkb.php',
        'CollationEt' => __DIR__ . '/includes/collation/CollationEt.php',
-       'CollationFa' => __DIR__ . '/includes/collation/CollationFa.php',
        'CommandLineInc' => __DIR__ . '/maintenance/commandLine.inc',
        'CommandLineInstaller' => __DIR__ . '/maintenance/install.php',
        'CommentStore' => __DIR__ . '/includes/CommentStore.php',
index 52dfc11..dd1a4db 100644 (file)
@@ -2861,6 +2861,7 @@ class OutputPage extends ContextSource {
 
                        $rlClient = new ResourceLoaderClientHtml( $context, [
                                'target' => $this->getTarget(),
+                               'nonce' => $this->getCSPNonce(),
                        ] );
                        $rlClient->setConfig( $this->getJSVars() );
                        $rlClient->setModules( $this->getModules( /*filter*/ true ) );
@@ -2907,7 +2908,7 @@ class OutputPage extends ContextSource {
                }
 
                $pieces[] = Html::element( 'title', null, $this->getHTMLTitle() );
-               $pieces[] = $this->getRlClient()->getHeadHtml( $this->getCSPNonce() );
+               $pieces[] = $this->getRlClient()->getHeadHtml();
                $pieces[] = $this->buildExemptModules();
                $pieces = array_merge( $pieces, array_values( $this->getHeadLinksArray() ) );
                $pieces = array_merge( $pieces, array_values( $this->mHeadItems ) );
index 30cae5a..f52dcae 100644 (file)
@@ -63,8 +63,6 @@ abstract class Collation {
                                return new CollationCkb;
                        case 'xx-uca-et':
                                return new CollationEt;
-                       case 'xx-uca-fa':
-                               return new CollationFa;
                        case 'uppercase-ab':
                                return new AbkhazUppercaseCollation;
                        case 'uppercase-ba':
diff --git a/includes/collation/CollationFa.php b/includes/collation/CollationFa.php
deleted file mode 100644 (file)
index 7410886..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<?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
- *
- * @file
- */
-
-/**
- * Temporary workaround for incorrect collation of Persian language ('fa') in ICU 52 (bug T139110).
- *
- * Replace with other letters that appear in an okish spot in the alphabet
- *
- *  - Characters 'و' 'ا' (often appear at the beginning of words)
- *  - Characters 'ٲ' 'ٳ' (may appear at the beginning of words in loanwords)
- *
- * @since 1.29
- */
-class CollationFa extends IcuCollation {
-
-       // Really hacky - replace with stuff from other blocks.
-       private $override = [
-               // U+0627 ARABIC LETTER ALEF => U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE
-               "\xd8\xa7" => "\xd8\xa3",
-               // U+0648 ARABIC LETTER WAW => U+0649 ARABIC LETTER ALEF MAKSURA
-               "\xd9\x88" => "\xd9\x89",
-               // U+0672 ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE => U+F3001 (private use area)
-               "\xd9\xb2" => "\xF3\xB3\x80\x81",
-               // U+0673 ARABIC LETTER ALEF WITH WAVY HAMZA BELOW => U+F3002 (private use area)
-               "\xd9\xb3" => "\xF3\xB3\x80\x82",
-       ];
-
-       public function __construct() {
-               parent::__construct( 'fa' );
-       }
-
-       public function getSortKey( $string ) {
-               $modified = strtr( $string, $this->override );
-               return parent::getSortKey( $modified );
-       }
-
-       public function getFirstLetter( $string ) {
-               if ( isset( $this->override[substr( $string, 0, 2 )] ) ) {
-                       return substr( $string, 0, 2 );
-               }
-               return parent::getFirstLetter( $string );
-       }
-}
index bee3d0c..2274793 100644 (file)
@@ -1503,7 +1503,7 @@ MESSAGE;
         * startup module if the client has adequate support for MediaWiki JavaScript code.
         *
         * @param string $script JavaScript code
-        * @param string $nonce Content-security-policy nonce, from OutputPage::getCSPNonce()
+        * @param string $nonce [optional] Content-Security-Policy nonce (from OutputPage::getCSPNonce)
         * @return WrappedString HTML
         */
        public static function makeInlineScript( $script, $nonce = null ) {
index d0a9c42..9eae7e8 100644 (file)
@@ -58,11 +58,15 @@ class ResourceLoaderClientHtml {
         * @param ResourceLoaderContext $context
         * @param array $options [optional] Array of options
         *  - 'target': Custom parameter passed to StartupModule.
+        *  - 'nonce': From OutputPage::getCSPNonce().
         */
        public function __construct( ResourceLoaderContext $context, array $options = [] ) {
                $this->context = $context;
                $this->resourceLoader = $context->getResourceLoader();
-               $this->options = $options;
+               $this->options = $options + [
+                       'target' => null,
+                       'nonce' => null,
+               ];
        }
 
        /**
@@ -248,10 +252,10 @@ class ResourceLoaderClientHtml {
         * - Inline scripts can't be asynchronous.
         * - For styles, earlier is better.
         *
-        * @param string $nonce From OutputPage::getCSPNonce()
         * @return string|WrappedStringList HTML
         */
-       public function getHeadHtml( $nonce ) {
+       public function getHeadHtml() {
+               $nonce = $this->options['nonce'];
                $data = $this->getData();
                $chunks = [];
 
@@ -327,7 +331,7 @@ class ResourceLoaderClientHtml {
 
                // Async scripts. Once the startup is loaded, inline RLQ scripts will run.
                // Pass-through a custom 'target' from OutputPage (T143066).
-               $startupQuery = isset( $this->options['target'] )
+               $startupQuery = $this->options['target'] !== null
                        ? [ 'target' => (string)$this->options['target'] ]
                        : [];
                $chunks[] = $this->getLoad(
@@ -379,12 +383,12 @@ class ResourceLoaderClientHtml {
         * @param ResourceLoaderContext $mainContext
         * @param array $modules One or more module names
         * @param string $only ResourceLoaderModule TYPE_ class constant
-        * @param array $extraQuery Array with extra query parameters for the request
-        * @param string $nonce See OutputPage::getCSPNonce() [Since 1.32]
+        * @param array $extraQuery [optional] Array with extra query parameters for the request
+        * @param string $nonce [optional] Content-Security-Policy nonce (from OutputPage::getCSPNonce)
         * @return string|WrappedStringList HTML
         */
        public static function makeLoad( ResourceLoaderContext $mainContext, array $modules, $only,
-               array $extraQuery, $nonce
+               array $extraQuery = [], $nonce = null
        ) {
                $rl = $mainContext->getResourceLoader();
                $chunks = [];
index e503d92..3ee7cea 100644 (file)
@@ -41,7 +41,7 @@ class SpecialTrackingCategories extends SpecialPage {
                $this->outputHeader();
                $this->getOutput()->allowClickjacking();
                $this->getOutput()->addHTML(
-                       Html::openElement( 'table', [ 'class' => 'mw-datatable',
+                       Html::openElement( 'table', [ 'class' => 'mw-datatable sortable',
                                'id' => 'mw-trackingcategories-table' ] ) . "\n" .
                        "<thead><tr>
                        <th>" .
index 3080fbf..5677ac8 100644 (file)
@@ -208,8 +208,16 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                                        if ( $hidelinks || $hidetrans || $hideredirs || $hideimages ) {
                                                $out->addHTML( $this->getFilterPanel() );
                                        }
-                                       $errMsg = is_int( $namespace ) ? 'nolinkshere-ns' : 'nolinkshere';
-                                       $out->addWikiMsg( $errMsg, $this->target->getPrefixedText() );
+                                       $msgKey = is_int( $namespace ) ? 'nolinkshere-ns-2' : 'nolinkshere-2';
+                                       $link = $this->getLinkRenderer()->makeKnownLink(
+                                               $this->target,
+                                               null,
+                                               [],
+                                               $this->target->isRedirect() ? [ 'redirect' => 'no' ] : []
+                                       );
+
+                                       $errMsg = $this->msg( $msgKey )->rawParams( $link )->parseAsBlock();
+                                       $out->addHTML( $errMsg );
                                        $out->setStatusCode( 404 );
                                }
                        }
@@ -273,7 +281,16 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                        if ( !$this->including() ) {
                                $out->addHTML( $this->whatlinkshereForm() );
                                $out->addHTML( $this->getFilterPanel() );
-                               $out->addWikiMsg( 'linkshere', $this->target->getPrefixedText() );
+
+                               $link = $this->getLinkRenderer()->makeKnownLink(
+                                       $this->target,
+                                       null,
+                                       [],
+                                       $this->target->isRedirect() ? [ 'redirect' => 'no' ] : []
+                               );
+
+                               $msg = $this->msg( 'linkshere-2' )->rawParams( $link )->parseAsBlock();
+                               $out->addHTML( $msg );
 
                                $prevnext = $this->getPrevNext( $prevId, $nextId );
                                $out->addHTML( $prevnext );
index 09d4b5e..d17332f 100644 (file)
@@ -70,6 +70,7 @@ class UsersPager extends AlphabeticPager {
                        $this->requestedGroup = '';
                }
                $this->editsOnly = $request->getBool( 'editsOnly' );
+               $this->temporaryGroupsOnly = $request->getBool( 'temporaryGroupsOnly' );
                $this->creationSort = $request->getBool( 'creationSort' );
                $this->including = $including;
                $this->mDefaultDirection = $request->getBool( 'desc' )
@@ -110,9 +111,13 @@ class UsersPager extends AlphabeticPager {
 
                $options = [];
 
+               if ( $this->requestedGroup != '' || $this->temporaryGroupsOnly ) {
+                       $conds[] = 'ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() ) .
+                       ( !$this->temporaryGroupsOnly ? ' OR ug_expiry IS NULL' : '' );
+               }
+
                if ( $this->requestedGroup != '' ) {
                        $conds['ug_group'] = $this->requestedGroup;
-                       $conds[] = 'ug_expiry IS NULL OR ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() );
                }
 
                if ( $this->requestedUser != '' ) {
@@ -296,6 +301,13 @@ class UsersPager extends AlphabeticPager {
                                'id' => 'editsOnly',
                                'default' => $this->editsOnly
                        ],
+                       'temporaryGroupsOnly' => [
+                               'type' => 'check',
+                               'label' => $this->msg( 'listusers-temporarygroupsonly' )->text(),
+                               'name' => 'temporaryGroupsOnly',
+                               'id' => 'temporaryGroupsOnly',
+                               'default' => $this->temporaryGroupsOnly
+                       ],
                        'creationSort' => [
                                'type' => 'check',
                                'label' => $this->msg( 'listusers-creationsort' )->text(),
index 9943212..40c9f65 100644 (file)
@@ -271,7 +271,7 @@ class Names {
                'li' => 'Limburgs', # Limburgian
                'lij' => 'Ligure', # Ligurian
                'liv' => 'Līvõ kēļ', # Livonian
-               'lki' => 'لەکی', # Laki
+               'lki' => 'لەکی', # Laki
                'lmo' => 'lumbaart', # Lombard
                'ln' => 'lingála', # Lingala
                'lo' => 'ລາວ', # Laotian
index 236d6e5..00756df 100644 (file)
        "listusers": "User list",
        "listusers-summary": "",
        "listusers-editsonly": "Show only users with edits",
+       "listusers-temporarygroupsonly": "Show only users in temporary user groups",
        "listusers-creationsort": "Sort by creation date",
        "listusers-desc": "Sort in descending order",
        "usereditcount": "$1 {{PLURAL:$1|edit|edits}}",
        "whatlinkshere-title": "Pages that link to \"$1\"",
        "whatlinkshere-summary": "",
        "whatlinkshere-page": "Page:",
-       "linkshere": "The following pages link to <strong>[[:$1]]</strong>:",
-       "nolinkshere": "No pages link to <strong>[[:$1]]</strong>.",
-       "nolinkshere-ns": "No pages link to <strong>[[:$1]]</strong> in the chosen namespace.",
+       "linkshere-2": "The following pages link to <strong>$1</strong>:",
+       "nolinkshere-2": "No pages link to <strong>$1</strong>.",
+       "nolinkshere-ns-2": "No pages link to <strong>$1</strong> in the chosen namespace.",
        "isredirect": "redirect page",
        "istemplate": "transclusion",
        "isimage": "file link",
index 0947db2..12de8bf 100644 (file)
        "listusers": "{{doc-special|ListUsers}}",
        "listusers-summary": "{{notranslate}}\nThe summary displayed at the top of [[Special:Listusers]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
        "listusers-editsonly": "Option in [[Special:ListUsers]].",
+       "listusers-temporarygroupsonly": "Option in [[Special:ListUsers]].",
        "listusers-creationsort": "Option in [[Special:ListUsers]].",
        "listusers-desc": "Used as label for the checkbox on [[Special:ListUsers]].",
        "usereditcount": "Shown behind every username on [[Special:ListUsers]]. Parameters:\n* $1 - number of edits",
        "whatlinkshere-title": "Title of the special page [[Special:WhatLinksHere]]. This page appears when you click on the 'What links here' button in the toolbox. $1 is the name of the page concerned.",
        "whatlinkshere-summary": "{{doc-specialpagesummary|whatlinkshere}}",
        "whatlinkshere-page": "{{Identical|Page}}",
-       "linkshere": "This message is the header line of the [[Special:WhatLinksHere/$1]] page generated by clicking \"What links here\" in the sidebar toolbox.\n\nIt is followed by a navigation bar built using {{msg-mw|Viewprevnext}}.\n\nParameters:\n* $1 - page title",
-       "nolinkshere": "Used in [[Special:WhatLinksHere]] if empty. Parameters:\n* $1 - page title\nSee also:\n* {{msg-mw|Nolinkshere-ns}}",
-       "nolinkshere-ns": "Used in [[Special:WhatLinksHere]] if empty. Parameters:\n* $1 - page title\nSee also:\n* {{msg-mw|Nolinkshere}}",
+       "linkshere-2": "This message is the header line of the [[Special:WhatLinksHere/$1]] page generated by clicking \"What links here\" in the sidebar toolbox.\n\nIt is followed by a navigation bar built using {{msg-mw|Viewprevnext}}.\n\nParameters:\n* $1 - HTML link to the page.",
+       "nolinkshere-2": "Used in [[Special:WhatLinksHere]] if empty. Parameters:\n* $1 - HTML link to the page\nSee also:\n* {{msg-mw|Nolinkshere-ns-html}}",
+       "nolinkshere-ns-2": "Used in [[Special:WhatLinksHere]] if empty. Parameters:\n* $1 - HTML link to the page\nSee also:\n* {{msg-mw|Nolinkshere-html}}",
        "isredirect": "Displayed in [[Special:WhatLinksHere]] (see [{{fullurl:Special:WhatLinksHere/Project:Translator|hidelinks=1}} Special:WhatLinksHere/Project:Translator] for example).\n\n{{Identical|Redirect page}}",
        "istemplate": "Means that a page (a template, specifically) is used as <code><nowiki>{{Page name}}</nowiki></code>.\nDisplayed in [[Special:WhatLinksHere]] (see [[Special:WhatLinksHere/Template:New portal]] for example).\nIf you are not sure how to translate this term, think of something like \"inclusion\", \"embedding\", or \"insertion\".\n{{Identical|Transclusion}}",
        "isimage": "This message is displayed on [[Special:WhatLinksHere]] for images. It means that the image is used on the page (as opposed to just being linked to like an non-image page).\n{{Identical|File link}}",
diff --git a/tests/phpunit/includes/collation/CollationFaTest.php b/tests/phpunit/includes/collation/CollationFaTest.php
deleted file mode 100644 (file)
index f745541..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-/**
- * @covers CollationFa
- */
-class CollationFaTest extends MediaWikiTestCase {
-
-       /*
-        * The ordering is a weird hack designed to work only with a very
-        * specific version of libicu, and as such can't really be unit tested
-        * against a random version of libicu
-        */
-
-       public function setUp() {
-               parent::setUp();
-               $this->checkPHPExtension( 'intl' );
-       }
-
-       /**
-        * @dataProvider provideGetFirstLetter
-        */
-       public function testGetFirstLetter( $letter, $str ) {
-               $coll = new CollationFa;
-               $this->assertEquals( $letter, $coll->getFirstLetter( $str ), $str );
-       }
-
-       public function provideGetFirstLetter() {
-               return [
-                       [
-                               '۷',
-                               '۷'
-                       ],
-                       [
-                               'ا',
-                               'ا'
-                       ],
-                       [
-                               'ا',
-                               'ایران'
-                       ],
-                       [
-                               'ب',
-                               'برلین'
-                       ],
-                       [
-                               'و',
-                               'واو'
-                       ],
-                       [ "\xd8\xa7", "\xd8\xa7Foo" ],
-                       [ "\xd9\x88", "\xd9\x88Foo" ],
-                       [ "\xd9\xb2", "\xd9\xb2Foo" ],
-                       [ "\xd9\xb3", "\xd9\xb3Foo" ],
-               ];
-       }
-}
index e763a19..1017632 100644 (file)
@@ -186,7 +186,9 @@ class ResourceLoaderClientHtmlTest extends PHPUnit\Framework\TestCase {
                $context = self::makeContext();
                $context->getResourceLoader()->register( self::makeSampleModules() );
 
-               $client = new ResourceLoaderClientHtml( $context );
+               $client = new ResourceLoaderClientHtml( $context, [
+                       'nonce' => false,
+               ] );
                $client->setConfig( [ 'key' => 'value' ] );
                $client->setModules( [
                        'test',
@@ -218,7 +220,7 @@ class ResourceLoaderClientHtmlTest extends PHPUnit\Framework\TestCase {
                // phpcs:enable
                $expected = self::expandVariables( $expected );
 
-               $this->assertEquals( $expected, $client->getHeadHtml( false ) );
+               $this->assertEquals( $expected, $client->getHeadHtml() );
        }
 
        /**
@@ -237,7 +239,7 @@ class ResourceLoaderClientHtmlTest extends PHPUnit\Framework\TestCase {
                        . '<script async="" src="/w/load.php?debug=false&amp;lang=nl&amp;modules=startup&amp;only=scripts&amp;skin=fallback&amp;target=example"></script>';
                // phpcs:enable
 
-               $this->assertEquals( $expected, $client->getHeadHtml( false ) );
+               $this->assertEquals( $expected, $client->getHeadHtml() );
        }
 
        /**
@@ -256,7 +258,7 @@ class ResourceLoaderClientHtmlTest extends PHPUnit\Framework\TestCase {
                        . '<script async="" src="/w/load.php?debug=false&amp;lang=nl&amp;modules=startup&amp;only=scripts&amp;skin=fallback"></script>';
                // phpcs:enable
 
-               $this->assertEquals( $expected, $client->getHeadHtml( false ) );
+               $this->assertEquals( $expected, $client->getHeadHtml() );
        }
 
        /**