Merge "API: ApiBase::getParameter() shouldn't throw on other params' errors"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 29 May 2018 19:04:27 +0000 (19:04 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 29 May 2018 19:04:28 +0000 (19:04 +0000)
13 files changed:
RELEASE-NOTES-1.32
includes/DefaultSettings.php
includes/parser/Parser.php
includes/resourceloader/ResourceLoader.php
includes/specials/SpecialPasswordPolicies.php
languages/i18n/en.json
languages/i18n/qqq.json
resources/src/mediawiki.htmlform.ooui.styles.less
resources/src/mediawiki.less/mediawiki.mixins.less
tests/parser/parserTests.txt
tests/phpunit/data/registration/good.json
tests/phpunit/includes/registration/ExtensionRegistryTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderTest.php

index bef3653..b016d0b 100644 (file)
@@ -123,6 +123,9 @@ because of Phabricator reports.
   The UtfNormal\Utils class from the utfnormal library should be used instead.
 * The deprecated UTF8_ and UNICODE_ constants were removed. The class constants
   from the UtfNormal\Constants class from the utfnormal library should be used
+* (T140807) The wgResourceLoaderLESSImportPaths configuration option was removed
+  from ResourceLoader. Instead, use `@import` statements in LESS to import
+  files directly from nearby directories within the same project.
 
 === Deprecations in 1.32 ===
 * Use of a StartProfiler.php file is deprecated in favour of placing
@@ -149,6 +152,7 @@ because of Phabricator reports.
   with the 'unwatch' action parameter instead.
 * IcuCollation::getICUVersion() is deprecated, as you can just use the PHP
   constant INTL_ICU_VERSION directly in all versions that MediaWiki supports.
+* Parser::fetchFile() is deprecated. Use ::fetchFileAndTitle() instead.
 
 === Other changes in 1.32 ===
 * Soft hyphens (U+00AD) are now automatically removed from titles; these
index 1f55d32..562d887 100644 (file)
@@ -3778,23 +3778,6 @@ $wgResourceLoaderLESSVars = [
        'deviceWidthTablet' => '720px',
 ];
 
-/**
- * Default import paths for LESS modules. LESS files referenced in @import
- * statements will be looked up here first, and relative to the importing file
- * second. To avoid collisions, it's important for the LESS files in these
- * directories to have a common, predictable file name prefix.
- *
- * Extensions need not (and should not) register paths in
- * $wgResourceLoaderLESSImportPaths. The import path includes the path of the
- * currently compiling LESS file, which allows each extension to freely import
- * files from its own tree.
- *
- * @since 1.22
- */
-$wgResourceLoaderLESSImportPaths = [
-       "$IP/resources/src/mediawiki.less/",
-];
-
 /**
  * Whether ResourceLoader should attempt to persist modules in localStorage on
  * browsers that support the Web Storage API.
index 2696f4d..dfd9602 100644 (file)
@@ -3689,8 +3689,10 @@ class Parser {
         * @param Title $title
         * @param array $options Array of options to RepoGroup::findFile
         * @return File|bool
+        * @deprecated since 1.32, use fetchFileAndTitle instead
         */
        public function fetchFile( $title, $options = [] ) {
+               wfDeprecated( __METHOD__, '1.32' );
                return $this->fetchFileAndTitle( $title, $options )[0];
        }
 
index 1b8a4a8..f3b6a70 100644 (file)
@@ -1711,6 +1711,7 @@ MESSAGE;
         * @return Less_Parser
         */
        public function getLessCompiler( $vars = [] ) {
+               global $IP;
                // When called from the installer, it is possible that a required PHP extension
                // is missing (at least for now; see T49564). If this is the case, throw an
                // exception (caught by the installer) to prevent a fatal error later on.
@@ -1720,9 +1721,9 @@ MESSAGE;
 
                $parser = new Less_Parser;
                $parser->ModifyVars( $vars );
-               $parser->SetImportDirs(
-                       array_fill_keys( $this->config->get( 'ResourceLoaderLESSImportPaths' ), '' )
-               );
+               $parser->SetImportDirs( [
+                       "$IP/resources/src/mediawiki.less/" => '',
+               );
                $parser->SetOption( 'relativeUrls', false );
 
                return $parser;
index 415f973..0a3a679 100644 (file)
@@ -44,7 +44,8 @@ class SpecialPasswordPolicies extends SpecialPage {
                $out = $this->getOutput();
                $out->addModuleStyles( 'mediawiki.special' );
 
-               $this->addHelpLink( 'Help:Password policies' );
+               // TODO: Have specific user documentation page for this feature
+               $this->addHelpLink( 'Manual:$wgPasswordPolicy' );
 
                $out->addHTML(
                        Xml::openElement( 'table', [ 'class' => 'wikitable mw-passwordpolicies-table' ] ) .
index f36c8ed..837e3b5 100644 (file)
        "unregistered-user-config": "For security reasons JavaScript, CSS and JSON user subpages cannot be loaded for unregistered users.",
        "passwordpolicies": "Password policies",
        "passwordpolicies-summary": "This is a list of the effective password policies for the user groups defined in this wiki.",
-       "passwordpolicies-helppage": "Manual:$wgPasswordPolicy",
        "passwordpolicies-group": "Group",
        "passwordpolicies-policies": "Policies",
        "passwordpolicies-policy-display": "<span class=\"passwordpolicies-policy\">$1 <code>($2)</code></span>",
index 417e0f7..139c91c 100644 (file)
        "unregistered-user-config": "Shown when viewing a user JS, CSS or JSON subpage with ?action=raw&ctype=<mime type> where there is no such user. It is shown as a paragraph after a header saying 'Forbidden'.",
        "passwordpolicies": "The name of the special page [[Special:PasswordPolicies]].",
        "passwordpolicies-summary": "The description used on [[Special:PasswordPolicies]].\n\nRefers to {{msg-mw|Passwordpolicies-helppage}}.",
-       "passwordpolicies-helppage": "The link used on [[Special:PasswordPolicies]].",
        "passwordpolicies-group": "The title of the column in the table, about user groups (like you are in the ''translator'' group).\n\n{{Identical|Group}}\n{{Related|Passwordpolicies}}",
        "passwordpolicies-policies": "The title of the column in the table, about password policies.\n{{Related|Passwordpolicies}}",
        "passwordpolicies-policy-display": "{{optional}}\nParameters:\n* $1 - the text from the \"passwordpolicies-policy-...\" messages, i.e. {{msg-mw|passwordpolicies-policy-minimalpasswordlength}}\n* $2 - the name of this password policy",
index 61a1c9c..0b56df1 100644 (file)
@@ -6,6 +6,8 @@
 
 @ooui-spacing-medium: 12 / @ooui-font-size-browser / @ooui-font-size-base; // equals `0.8571429em`≈`12px`
 @ooui-spacing-large: 16 / @ooui-font-size-browser / @ooui-font-size-base; // equals `1.1428571em`≈`16px`
+@ooui-padding-horizontal: 12 / @ooui-font-size-browser / @ooui-font-size-base;
+@ooui-padding-vertical: 4 / @ooui-font-size-browser / @ooui-font-size-base; // equals `0.285714em`≈`4px`
 
 .mw-htmlform-ooui-wrapper.oo-ui-panelLayout-padded {
        padding: @ooui-spacing-medium @ooui-spacing-large @ooui-spacing-large;
        }
 
        .mw-htmlform-matrix {
-               border-spacing: 0;
+               border-spacing: 0 2px;
 
                td {
-                       padding: 0.35em 0.7em;
+                       padding: @ooui-padding-vertical @ooui-padding-horizontal;
+                       text-align: center;
                        .transition( background-color 250ms );
+
+                       &:first-child {
+                               text-align: left;
+                       }
                }
 
                tbody tr:nth-child( even ) td {
@@ -40,6 +47,7 @@
 
                tbody tr:first-child td {
                        background-color: #fff;
+                       padding-bottom: 0;
                }
 
                td.first {
index 53dccc2..55be237 100644 (file)
@@ -1,6 +1,6 @@
 // Common Less mixin library for MediaWiki
 //
-// By default the folder containing this file is included in $wgResourceLoaderLESSImportPaths,
+// By default the folder containing this file is included in the LESS import paths,
 // which makes this file importable by all less files via `@import 'mediawiki.mixins';`.
 //
 // The mixins included below are considered a public interface for MediaWiki extensions.
index bffc56e..216d7e5 100644 (file)
@@ -62,6 +62,12 @@ Template:Foo
 FOO
 !!endarticle
 
+!! article
+Template:redirect to foo
+!! text
+#REDIRECT [[Template:Foo]]
+!! endarticle
+
 !! article
 Template:Blank
 !! text
@@ -1861,6 +1867,17 @@ maxtemplatedepth=1
 </p>
 !! end
 
+!! test
+multiple templates that are redirects
+!! wikitext
+{{redirect to foo}}
+{{redirect to foo}}
+!! html
+<p>FOO
+FOO
+</p>
+!! end
+
 !! test
 Multiple comments should still parse as SOL-transparent
 !! options
index ad16c5e..cfad069 100644 (file)
@@ -1,4 +1,12 @@
 {
        "name": "FooBar",
-       "manifest_version": 1
+       "attributes": {
+               "FooBar": {
+                       "Attr": [ "test" ]
+               },
+               "NotLoaded": {
+                       "Attr": [ "test2" ]
+               }
+       },
+       "manifest_version": 2
 }
index 67bc088..a372c8c 100644 (file)
@@ -51,6 +51,26 @@ class ExtensionRegistryTest extends MediaWikiTestCase {
                $registry->loadFromQueue();
        }
 
+       public function testLoadFromQueue() {
+               $registry = new ExtensionRegistry();
+               $registry->queue( "{$this->dataDir}/good.json" );
+               $registry->loadFromQueue();
+               $this->assertArrayHasKey( 'FooBar', $registry->getAllThings() );
+               $this->assertTrue( $registry->isLoaded( 'FooBar' ) );
+               $this->assertSame( [ 'test' ], $registry->getAttribute( 'FooBarAttr' ) );
+               $this->assertSame( [], $registry->getAttribute( 'NotLoadedAttr' ) );
+       }
+
+       /**
+        * @expectedException PHPUnit_Framework_Error
+        */
+       public function testReadFromQueue_nonexistent() {
+               $registry = new ExtensionRegistry();
+               $registry->readFromQueue( [
+                       __DIR__ . '/doesnotexist.json' => 1
+               ] );
+       }
+
        /**
         * @dataProvider provideExportExtractedDataGlobals
         */
index 71a6339..e0b8c5e 100644 (file)
@@ -8,7 +8,6 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
                parent::setUp();
 
                $this->setMwGlobals( [
-                       'wgResourceLoaderLESSImportPaths' => [],
                        'wgResourceLoaderLESSVars' => [
                                'foo'  => '2px',
                                'Foo' => '#eeeeee',
@@ -737,6 +736,21 @@ mw.example();
                $this->assertEquals( $expected, $response, $message ?: 'Response' );
        }
 
+       /**
+        * @covers ResourceLoader::makeModuleResponse
+        */
+       public function testMakeModuleResponseEmpty() {
+               $rl = new EmptyResourceLoader();
+               $context = $this->getResourceLoaderContext(
+                       [ 'modules' => '', 'only' => 'scripts' ],
+                       $rl
+               );
+
+               $response = $rl->makeModuleResponse( $context, [] );
+               $this->assertSame( [], $rl->getErrors(), 'Errors' );
+               $this->assertRegExp( '/^\/\*.+no modules were requested.+\*\/$/ms', $response );
+       }
+
        /**
         * Verify that when building module content in a load.php response,
         * an exception from one module will not break script output from
@@ -809,7 +823,7 @@ mw.example();
 
                $this->assertCount( 2, $errors );
                $this->assertRegExp( '/Ferry not found/', $errors[0] );
-               $this->assertRegExp( '/Problem.+\n\s*"ferry":\s*"error"/m', $errors[1] );
+               $this->assertRegExp( '/Problem.+"ferry":\s*"error"/ms', $errors[1] );
                $this->assertEquals(
                        '.foo{}.bar{}',
                        $response