Merge "RCFilters: Make extra filters footer non-sticky"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 27 Jun 2017 19:14:08 +0000 (19:14 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 27 Jun 2017 19:14:09 +0000 (19:14 +0000)
130 files changed:
includes/MediaWikiServices.php
includes/PageProps.php
includes/ServiceWiring.php
includes/WatchedItemQueryService.php
includes/WatchedItemStore.php
includes/Xml.php
includes/api/ApiAMCreateAccount.php
includes/api/ApiAuthManagerHelper.php
includes/api/ApiChangeAuthenticationData.php
includes/api/ApiCheckToken.php
includes/api/ApiClientLogin.php
includes/api/ApiHelp.php
includes/api/ApiHelpParamValueMessage.php
includes/api/ApiLinkAccount.php
includes/api/ApiOpenSearch.php
includes/api/ApiQueryAllDeletedRevisions.php
includes/api/ApiQueryAllRevisions.php
includes/api/ApiQueryAuthManagerInfo.php
includes/api/ApiQueryBacklinksprop.php
includes/api/ApiQueryContributors.php
includes/api/ApiQueryDeletedRevisions.php
includes/api/ApiQueryInfo.php
includes/api/ApiQueryPagePropNames.php
includes/api/ApiQueryPagesWithProp.php
includes/api/ApiQueryPrefixSearch.php
includes/api/ApiQueryTokens.php
includes/api/ApiQueryUsers.php
includes/api/ApiRemoveAuthenticationData.php
includes/api/ApiResetPassword.php
includes/api/ApiRevisionDelete.php
includes/api/ApiSerializable.php
includes/api/ApiSetNotificationTimestamp.php
includes/changes/EnhancedChangesList.php
includes/debug/logger/LegacyLogger.php
includes/debug/logger/LegacySpi.php
includes/debug/logger/LoggerFactory.php
includes/debug/logger/MonologSpi.php
includes/debug/logger/NullSpi.php
includes/debug/logger/Spi.php
includes/debug/logger/monolog/LegacyFormatter.php
includes/debug/logger/monolog/LegacyHandler.php
includes/debug/logger/monolog/LineFormatter.php
includes/debug/logger/monolog/SyslogHandler.php
includes/debug/logger/monolog/WikiProcessor.php
includes/diff/DifferenceEngine.php
includes/filerepo/ForeignDBViaLBRepo.php
includes/filerepo/LocalRepo.php
includes/filerepo/file/LocalFile.php
includes/htmlform/HTMLFormElement.php
includes/htmlform/fields/HTMLUsersMultiselectField.php
includes/installer/DatabaseInstaller.php
includes/installer/Installer.php
includes/libs/CSSMin.php
includes/libs/HashRing.php
includes/libs/ObjectFactory.php
includes/libs/XhprofData.php
includes/libs/filebackend/FileBackendMultiWrite.php
includes/libs/objectcache/BagOStuff.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabaseMysqlBase.php
includes/libs/rdbms/database/DatabaseSqlite.php
includes/libs/rdbms/database/resultwrapper/FakeResultWrapper.php
includes/libs/rdbms/exception/DBTransactionError.php
includes/libs/rdbms/lbfactory/LBFactory.php
includes/libs/stats/SamplingStatsdClient.php
includes/libs/virtualrest/VirtualRESTServiceClient.php
includes/linkeddata/PageDataRequestHandler.php
includes/logging/RightsLogFormatter.php
includes/page/WikiPage.php
includes/parser/Parser.php
includes/profiler/ProfilerSectionOnly.php
includes/profiler/ProfilerXhprof.php
includes/registration/ExtensionProcessor.php
includes/registration/ExtensionRegistry.php
includes/resourceloader/ResourceLoaderJqueryMsgModule.php
includes/search/SearchEngine.php
includes/search/SearchSuggestionSet.php
includes/session/MetadataMergeException.php
includes/skins/SkinApi.php
includes/skins/SkinApiTemplate.php
includes/specialpage/SpecialPage.php
includes/specials/SpecialBotPasswords.php
includes/specials/SpecialChangeContentModel.php
includes/specials/SpecialMovepage.php
includes/specials/SpecialPagesWithProp.php
includes/specials/SpecialUserrights.php
includes/specials/SpecialVersion.php
includes/tidy/Balancer.php
includes/user/User.php
includes/utils/BatchRowUpdate.php
includes/utils/ZipDirectoryReader.php
maintenance/CodeCleanerGlobalsPass.inc
maintenance/validateRegistrationFile.php
phpcs.xml
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js
tests/parser/ParserTestRunner.php
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/GlobalFunctions/wfArrayFilterTest.php
tests/phpunit/includes/LinkerTest.php
tests/phpunit/includes/MediaWikiServicesTest.php
tests/phpunit/includes/Services/ServiceContainerTest.php
tests/phpunit/includes/Services/TestWiring1.php
tests/phpunit/includes/Services/TestWiring2.php
tests/phpunit/includes/TestLogger.php
tests/phpunit/includes/WatchedItemQueryServiceUnitTest.php
tests/phpunit/includes/WatchedItemStoreUnitTest.php
tests/phpunit/includes/api/ApiPageSetTest.php
tests/phpunit/includes/api/ApiQueryWatchlistIntegrationTest.php
tests/phpunit/includes/api/RandomImageGenerator.php
tests/phpunit/includes/config/ConfigFactoryTest.php
tests/phpunit/includes/content/ContentHandlerTest.php
tests/phpunit/includes/db/DatabaseMysqlBaseTest.php
tests/phpunit/includes/jobqueue/JobTest.php
tests/phpunit/includes/libs/DeferredStringifierTest.php
tests/phpunit/includes/libs/ObjectFactoryTest.php
tests/phpunit/includes/libs/XhprofDataTest.php
tests/phpunit/includes/libs/XmlTypeCheckTest.php
tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
tests/phpunit/includes/search/SearchEnginePrefixTest.php
tests/phpunit/includes/search/SearchSuggestionSetTest.php
tests/phpunit/includes/site/CachingSiteStoreTest.php
tests/phpunit/includes/specials/SpecialSearchTest.php
tests/phpunit/includes/utils/BatchRowUpdateTest.php
tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js

index b63c769..6161ee7 100644 (file)
@@ -377,7 +377,7 @@ class MediaWikiServices extends ServiceContainer {
                parent::__construct();
 
                // Register the given Config object as the bootstrap config service.
-               $this->defineService( 'BootstrapConfig', function() use ( $config ) {
+               $this->defineService( 'BootstrapConfig', function () use ( $config ) {
                        return $config;
                } );
        }
index 382d089..dac756e 100644 (file)
@@ -55,7 +55,7 @@ class PageProps {
                }
                $previousValue = self::$instance;
                self::$instance = $store;
-               return new ScopedCallback( function() use ( $previousValue ) {
+               return new ScopedCallback( function () use ( $previousValue ) {
                        self::$instance = $previousValue;
                } );
        }
index 6afabed..2dfcc42 100644 (file)
@@ -43,7 +43,7 @@ use MediaWiki\Logger\LoggerFactory;
 use MediaWiki\MediaWikiServices;
 
 return [
-       'DBLoadBalancerFactory' => function( MediaWikiServices $services ) {
+       'DBLoadBalancerFactory' => function ( MediaWikiServices $services ) {
                $mainConfig = $services->getMainConfig();
 
                $lbConf = MWLBFactory::applyDefaultConfig(
@@ -56,12 +56,12 @@ return [
                return new $class( $lbConf );
        },
 
-       'DBLoadBalancer' => function( MediaWikiServices $services ) {
+       'DBLoadBalancer' => function ( MediaWikiServices $services ) {
                // just return the default LB from the DBLoadBalancerFactory service
                return $services->getDBLoadBalancerFactory()->getMainLB();
        },
 
-       'SiteStore' => function( MediaWikiServices $services ) {
+       'SiteStore' => function ( MediaWikiServices $services ) {
                $rawSiteStore = new DBSiteStore( $services->getDBLoadBalancer() );
 
                // TODO: replace wfGetCache with a CacheFactory service.
@@ -71,7 +71,7 @@ return [
                return new CachingSiteStore( $rawSiteStore, $cache );
        },
 
-       'SiteLookup' => function( MediaWikiServices $services ) {
+       'SiteLookup' => function ( MediaWikiServices $services ) {
                $cacheFile = $services->getMainConfig()->get( 'SitesCacheFile' );
 
                if ( $cacheFile !== false ) {
@@ -82,7 +82,7 @@ return [
                }
        },
 
-       'ConfigFactory' => function( MediaWikiServices $services ) {
+       'ConfigFactory' => function ( MediaWikiServices $services ) {
                // Use the bootstrap config to initialize the ConfigFactory.
                $registry = $services->getBootstrapConfig()->get( 'ConfigRegistry' );
                $factory = new ConfigFactory();
@@ -93,12 +93,12 @@ return [
                return $factory;
        },
 
-       'MainConfig' => function( MediaWikiServices $services ) {
+       'MainConfig' => function ( MediaWikiServices $services ) {
                // Use the 'main' config from the ConfigFactory service.
                return $services->getConfigFactory()->makeConfig( 'main' );
        },
 
-       'InterwikiLookup' => function( MediaWikiServices $services ) {
+       'InterwikiLookup' => function ( MediaWikiServices $services ) {
                global $wgContLang; // TODO: manage $wgContLang as a service
                $config = $services->getMainConfig();
                return new ClassicInterwikiLookup(
@@ -111,26 +111,26 @@ return [
                );
        },
 
-       'StatsdDataFactory' => function( MediaWikiServices $services ) {
+       'StatsdDataFactory' => function ( MediaWikiServices $services ) {
                return new BufferingStatsdDataFactory(
                        rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' )
                );
        },
 
-       'EventRelayerGroup' => function( MediaWikiServices $services ) {
+       'EventRelayerGroup' => function ( MediaWikiServices $services ) {
                return new EventRelayerGroup( $services->getMainConfig()->get( 'EventRelayerConfig' ) );
        },
 
-       'SearchEngineFactory' => function( MediaWikiServices $services ) {
+       'SearchEngineFactory' => function ( MediaWikiServices $services ) {
                return new SearchEngineFactory( $services->getSearchEngineConfig() );
        },
 
-       'SearchEngineConfig' => function( MediaWikiServices $services ) {
+       'SearchEngineConfig' => function ( MediaWikiServices $services ) {
                global $wgContLang;
                return new SearchEngineConfig( $services->getMainConfig(), $wgContLang );
        },
 
-       'SkinFactory' => function( MediaWikiServices $services ) {
+       'SkinFactory' => function ( MediaWikiServices $services ) {
                $factory = new SkinFactory();
 
                $names = $services->getMainConfig()->get( 'ValidSkinNames' );
@@ -153,7 +153,7 @@ return [
                return $factory;
        },
 
-       'WatchedItemStore' => function( MediaWikiServices $services ) {
+       'WatchedItemStore' => function ( MediaWikiServices $services ) {
                $store = new WatchedItemStore(
                        $services->getDBLoadBalancer(),
                        new HashBagOStuff( [ 'maxKeys' => 100 ] ),
@@ -163,11 +163,11 @@ return [
                return $store;
        },
 
-       'WatchedItemQueryService' => function( MediaWikiServices $services ) {
+       'WatchedItemQueryService' => function ( MediaWikiServices $services ) {
                return new WatchedItemQueryService( $services->getDBLoadBalancer() );
        },
 
-       'CryptRand' => function( MediaWikiServices $services ) {
+       'CryptRand' => function ( MediaWikiServices $services ) {
                $secretKey = $services->getMainConfig()->get( 'SecretKey' );
                return new CryptRand(
                        [
@@ -178,7 +178,7 @@ return [
                                // for a little more variance
                                'wfWikiID',
                                // If we have a secret key set then throw it into the state as well
-                               function() use ( $secretKey ) {
+                               function () use ( $secretKey ) {
                                        return $secretKey ?: '';
                                }
                        ],
@@ -192,7 +192,7 @@ return [
                );
        },
 
-       'CryptHKDF' => function( MediaWikiServices $services ) {
+       'CryptHKDF' => function ( MediaWikiServices $services ) {
                $config = $services->getMainConfig();
 
                $secret = $config->get( 'HKDFSecret' ) ?: $config->get( 'SecretKey' );
@@ -215,13 +215,13 @@ return [
                );
        },
 
-       'MediaHandlerFactory' => function( MediaWikiServices $services ) {
+       'MediaHandlerFactory' => function ( MediaWikiServices $services ) {
                return new MediaHandlerFactory(
                        $services->getMainConfig()->get( 'MediaHandlers' )
                );
        },
 
-       'MimeAnalyzer' => function( MediaWikiServices $services ) {
+       'MimeAnalyzer' => function ( MediaWikiServices $services ) {
                $logger = LoggerFactory::getInstance( 'Mime' );
                $mainConfig = $services->getMainConfig();
                $params = [
@@ -274,7 +274,7 @@ return [
                return new MimeMagic( $params );
        },
 
-       'ProxyLookup' => function( MediaWikiServices $services ) {
+       'ProxyLookup' => function ( MediaWikiServices $services ) {
                $mainConfig = $services->getMainConfig();
                return new ProxyLookup(
                        $mainConfig->get( 'SquidServers' ),
@@ -282,26 +282,26 @@ return [
                );
        },
 
-       'Parser' => function( MediaWikiServices $services ) {
+       'Parser' => function ( MediaWikiServices $services ) {
                $conf = $services->getMainConfig()->get( 'ParserConf' );
                return ObjectFactory::constructClassInstance( $conf['class'], [ $conf ] );
        },
 
-       'LinkCache' => function( MediaWikiServices $services ) {
+       'LinkCache' => function ( MediaWikiServices $services ) {
                return new LinkCache(
                        $services->getTitleFormatter(),
                        $services->getMainWANObjectCache()
                );
        },
 
-       'LinkRendererFactory' => function( MediaWikiServices $services ) {
+       'LinkRendererFactory' => function ( MediaWikiServices $services ) {
                return new LinkRendererFactory(
                        $services->getTitleFormatter(),
                        $services->getLinkCache()
                );
        },
 
-       'LinkRenderer' => function( MediaWikiServices $services ) {
+       'LinkRenderer' => function ( MediaWikiServices $services ) {
                global $wgUser;
 
                if ( defined( 'MW_NO_SESSION' ) ) {
@@ -311,11 +311,11 @@ return [
                }
        },
 
-       'GenderCache' => function( MediaWikiServices $services ) {
+       'GenderCache' => function ( MediaWikiServices $services ) {
                return new GenderCache();
        },
 
-       '_MediaWikiTitleCodec' => function( MediaWikiServices $services ) {
+       '_MediaWikiTitleCodec' => function ( MediaWikiServices $services ) {
                global $wgContLang;
 
                return new MediaWikiTitleCodec(
@@ -325,15 +325,15 @@ return [
                );
        },
 
-       'TitleFormatter' => function( MediaWikiServices $services ) {
+       'TitleFormatter' => function ( MediaWikiServices $services ) {
                return $services->getService( '_MediaWikiTitleCodec' );
        },
 
-       'TitleParser' => function( MediaWikiServices $services ) {
+       'TitleParser' => function ( MediaWikiServices $services ) {
                return $services->getService( '_MediaWikiTitleCodec' );
        },
 
-       'MainObjectStash' => function( MediaWikiServices $services ) {
+       'MainObjectStash' => function ( MediaWikiServices $services ) {
                $mainConfig = $services->getMainConfig();
 
                $id = $mainConfig->get( 'MainStash' );
@@ -345,7 +345,7 @@ return [
                return \ObjectCache::newFromParams( $mainConfig->get( 'ObjectCaches' )[$id] );
        },
 
-       'MainWANObjectCache' => function( MediaWikiServices $services ) {
+       'MainWANObjectCache' => function ( MediaWikiServices $services ) {
                $mainConfig = $services->getMainConfig();
 
                $id = $mainConfig->get( 'MainWANCache' );
@@ -365,7 +365,7 @@ return [
                return \ObjectCache::newWANCacheFromParams( $params );
        },
 
-       'LocalServerObjectCache' => function( MediaWikiServices $services ) {
+       'LocalServerObjectCache' => function ( MediaWikiServices $services ) {
                $mainConfig = $services->getMainConfig();
 
                if ( function_exists( 'apc_fetch' ) ) {
@@ -388,7 +388,7 @@ return [
                return \ObjectCache::newFromParams( $mainConfig->get( 'ObjectCaches' )[$id] );
        },
 
-       'VirtualRESTServiceClient' => function( MediaWikiServices $services ) {
+       'VirtualRESTServiceClient' => function ( MediaWikiServices $services ) {
                $config = $services->getMainConfig()->get( 'VirtualRestConfig' );
 
                $vrsClient = new VirtualRESTServiceClient( new MultiHttpClient( [] ) );
@@ -406,11 +406,11 @@ return [
                return $vrsClient;
        },
 
-       'ConfiguredReadOnlyMode' => function( MediaWikiServices $services ) {
+       'ConfiguredReadOnlyMode' => function ( MediaWikiServices $services ) {
                return new ConfiguredReadOnlyMode( $services->getMainConfig() );
        },
 
-       'ReadOnlyMode' => function( MediaWikiServices $services ) {
+       'ReadOnlyMode' => function ( MediaWikiServices $services ) {
                return new ReadOnlyMode(
                        $services->getConfiguredReadOnlyMode(),
                        $services->getDBLoadBalancer()
index 22d5439..1fafb24 100644 (file)
@@ -313,7 +313,7 @@ class WatchedItemQueryService {
                $allFields = get_object_vars( $row );
                $rcKeys = array_filter(
                        array_keys( $allFields ),
-                       function( $key ) {
+                       function ( $key ) {
                                return substr( $key, 0, 3 ) === 'rc_';
                        }
                );
index 06f93c6..69a9df2 100644 (file)
@@ -104,7 +104,7 @@ class WatchedItemStore implements StatsdAwareInterface {
                }
                $previousValue = $this->deferredUpdatesAddCallableUpdateCallback;
                $this->deferredUpdatesAddCallableUpdateCallback = $callback;
-               return new ScopedCallback( function() use ( $previousValue ) {
+               return new ScopedCallback( function () use ( $previousValue ) {
                        $this->deferredUpdatesAddCallableUpdateCallback = $previousValue;
                } );
        }
@@ -127,7 +127,7 @@ class WatchedItemStore implements StatsdAwareInterface {
                }
                $previousValue = $this->revisionGetTimestampFromIdCallback;
                $this->revisionGetTimestampFromIdCallback = $callback;
-               return new ScopedCallback( function() use ( $previousValue ) {
+               return new ScopedCallback( function () use ( $previousValue ) {
                        $this->revisionGetTimestampFromIdCallback = $previousValue;
                } );
        }
@@ -821,7 +821,7 @@ class WatchedItemStore implements StatsdAwareInterface {
                // Calls DeferredUpdates::addCallableUpdate in normal operation
                call_user_func(
                        $this->deferredUpdatesAddCallableUpdateCallback,
-                       function() use ( $job ) {
+                       function () use ( $job ) {
                                $job->run();
                        }
                );
index 8289b81..d016433 100644 (file)
@@ -826,4 +826,3 @@ class Xml {
                return $s;
        }
 }
-
index b8bd511..72a36d7 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright Â© 2016 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2016 Wikimedia Foundation and contributors
  *
  * 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
index 8862cc7..3a9fb73 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright Â© 2016 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2016 Wikimedia Foundation and contributors
  *
  * 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
index 35c4e56..d4a26ad 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright Â© 2016 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2016 Wikimedia Foundation and contributors
  *
  * 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
index 480915e..e1be8ef 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Created on Jan 29, 2015
  *
- * Copyright Â© 2015 Brad Jorsch bjorsch@wikimedia.org
+ * Copyright Â© 2015 Wikimedia Foundation and contributors
  *
  * 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
index 0d512b3..65dea93 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright Â© 2016 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2016 Wikimedia Foundation and contributors
  *
  * 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
index 3fd29ae..12e778b 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Created on Aug 29, 2014
  *
- * Copyright Â© 2014 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2014 Wikimedia Foundation and contributors
  *
  * 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
index ebe4e26..162b7cd 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Created on Dec 22, 2014
  *
- * Copyright Â© 2014 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2014 Wikimedia Foundation and contributors
  *
  * 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
index f5c5dee..9553f29 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright Â© 2016 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2016 Wikimedia Foundation and contributors
  *
  * 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
index 9eb5793..419fd14 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright Â© 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
  * Copyright Â© 2008 Brion Vibber <brion@wikimedia.org>
- * Copyright Â© 2014 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2014 Wikimedia Foundation and contributors
  *
  * 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
index 5682cc2..b22bb1f 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Created on Oct 3, 2014
  *
- * Copyright Â© 2014 Brad Jorsch "bjorsch@wikimedia.org"
+ * Copyright Â© 2014 Wikimedia Foundation and contributors
  *
  * Heavily based on ApiQueryDeletedrevs,
  * Copyright Â© 2007 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
index 20746c9..8f7d6eb 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Created on Sep 27, 2015
  *
- * Copyright Â© 2015 Brad Jorsch "bjorsch@wikimedia.org"
+ * Copyright Â© 2015 Wikimedia Foundation and contributors
  *
  * 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
index c775942..d23d898 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright Â© 2016 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2016 Wikimedia Foundation and contributors
  *
  * 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
index 00cbcd9..1db15f8 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Created on Aug 19, 2014
  *
- * Copyright Â© 2014 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2014 Wikimedia Foundation and contributors
  *
  * 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
index 693d954..f802d9e 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Created on Nov 14, 2013
  *
- * Copyright Â© 2013 Brad Jorsch
+ * Copyright Â© 2013 Wikimedia Foundation and contributors
  *
  * 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
index 90fd695..8e4752e 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Created on Oct 3, 2014
  *
- * Copyright Â© 2014 Brad Jorsch "bjorsch@wikimedia.org"
+ * Copyright Â© 2014 Wikimedia Foundation and contributors
  *
  * Heavily based on ApiQueryDeletedrevs,
  * Copyright Â© 2007 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
index c2cdfe4..6b8f98c 100644 (file)
@@ -766,7 +766,7 @@ class ApiQueryInfo extends ApiQueryBase {
                if ( $this->fld_watched ) {
                        foreach ( $timestamps as $namespaceId => $dbKeys ) {
                                $this->watched[$namespaceId] = array_map(
-                                       function( $x ) {
+                                       function ( $x ) {
                                                return $x !== false;
                                        },
                                        $dbKeys
@@ -847,7 +847,7 @@ class ApiQueryInfo extends ApiQueryBase {
                                $timestamps[$row->page_namespace][$row->page_title] = $revTimestamp - $age;
                        }
                        $titlesWithThresholds = array_map(
-                               function( LinkTarget $target ) use ( $timestamps ) {
+                               function ( LinkTarget $target ) use ( $timestamps ) {
                                        return [
                                                $target, $timestamps[$target->getNamespace()][$target->getDBkey()]
                                        ];
@@ -860,7 +860,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        $titlesWithThresholds = array_merge(
                                $titlesWithThresholds,
                                array_map(
-                                       function( LinkTarget $target ) {
+                                       function ( LinkTarget $target ) {
                                                return [ $target, null ];
                                        },
                                        $this->missing
index ff97668..2d56983 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Created on January 21, 2013
  *
- * Copyright Â© 2013 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2013 Wikimedia Foundation and contributors
  *
  * 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
@@ -21,7 +21,6 @@
  *
  * @file
  * @since 1.21
- * @author Brad Jorsch
  */
 
 /**
index e90356d..97f79b6 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Created on December 31, 2012
  *
- * Copyright Â© 2012 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2012 Wikimedia Foundation and contributors
  *
  * 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
@@ -21,7 +21,6 @@
  *
  * @file
  * @since 1.21
- * @author Brad Jorsch
  */
 
 /**
index 5606f3c..2fbc518 100644 (file)
@@ -54,7 +54,7 @@ class ApiQueryPrefixSearch extends ApiQueryGeneratorBase {
                $titles = $searchEngine->extractTitles( $searchEngine->completionSearchWithVariants( $search ) );
 
                if ( $resultPageSet ) {
-                       $resultPageSet->setRedirectMergePolicy( function( array $current, array $new ) {
+                       $resultPageSet->setRedirectMergePolicy( function ( array $current, array $new ) {
                                if ( !isset( $current['index'] ) || $new['index'] < $current['index'] ) {
                                        $current['index'] = $new['index'];
                                }
index 85205c8..0e46fd0 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Created on August 8, 2014
  *
- * Copyright Â© 2014 Brad Jorsch bjorsch@wikimedia.org
+ * Copyright Â© 2014 Wikimedia Foundation and contributors
  *
  * 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
index a5d06c8..5b094cd 100644 (file)
@@ -214,7 +214,7 @@ class ApiQueryUsers extends ApiQueryBase {
                                }
 
                                if ( isset( $this->prop['groupmemberships'] ) ) {
-                                       $data[$key]['groupmemberships'] = array_map( function( $ugm ) {
+                                       $data[$key]['groupmemberships'] = array_map( function ( $ugm ) {
                                                return [
                                                        'group' => $ugm->getGroup(),
                                                        'expiry' => ApiResult::formatExpiry( $ugm->getExpiry() ),
index 661b50c..e18484b 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright Â© 2016 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2016 Wikimedia Foundation and contributors
  *
  * 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
index a4b51b5..7783826 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright Â© 2016 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2016 Wikimedia Foundation and contributors
  *
  * 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
index 4580aa2..9d71a7d 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Created on Jun 25, 2013
  *
- * Copyright Â© 2013 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2013 Wikimedia Foundation and contributors
  *
  * 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
index 70e93a6..a41f655 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Created on Feb 25, 2015
  *
- * Copyright Â© 2015 Brad Jorsch "bjorsch@wikimedia.org"
+ * Copyright Â© 2015 Wikimedia Foundation and contributors
  *
  * 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
index 1fc8fc2..663416e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Created on Jun 18, 2012
  *
- * Copyright Â© 2012 Brad Jorsch
+ * Copyright Â© 2012 Wikimedia Foundation and contributors
  *
  * 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
index cbbbfeb..64d4aa7 100644 (file)
@@ -685,7 +685,7 @@ class EnhancedChangesList extends ChangesList {
                }
                $attribs = $data['attribs'];
                unset( $data['attribs'] );
-               $attribs = wfArrayFilterByKey( $attribs, function( $key ) {
+               $attribs = wfArrayFilterByKey( $attribs, function ( $key ) {
                        return $key === 'class' || Sanitizer::isReservedDataAttribute( $key );
                } );
 
index baf4637..6359509 100644 (file)
@@ -43,8 +43,7 @@ use UDPTransport;
  *
  * @see \MediaWiki\Logger\LoggerFactory
  * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2014 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2014 Wikimedia Foundation and contributors
  */
 class LegacyLogger extends AbstractLogger {
 
index 4cf8313..8e750ca 100644 (file)
@@ -32,8 +32,7 @@ namespace MediaWiki\Logger;
  *
  * @see \MediaWiki\Logger\LoggerFactory
  * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2014 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2014 Wikimedia Foundation and contributors
  */
 class LegacySpi implements Spi {
 
index ce92dbd..c183ff1 100644 (file)
@@ -40,8 +40,7 @@ use ObjectFactory;
  *
  * @see \MediaWiki\Logger\Spi
  * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2014 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2014 Wikimedia Foundation and contributors
  */
 class LoggerFactory {
 
index f44ff1c..197b269 100644 (file)
@@ -110,8 +110,7 @@ use ObjectFactory;
  *
  * @see https://github.com/Seldaek/monolog
  * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2014 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2014 Wikimedia Foundation and contributors
  */
 class MonologSpi implements Spi {
 
index 82308d0..4862157 100644 (file)
@@ -34,8 +34,7 @@ use Psr\Log\NullLogger;
  *
  * @see \MediaWiki\Logger\LoggerFactory
  * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2014 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2014 Wikimedia Foundation and contributors
  */
 class NullSpi implements Spi {
 
index 044789f..8e0875f 100644 (file)
@@ -31,8 +31,7 @@ namespace MediaWiki\Logger;
  *
  * @see \MediaWiki\Logger\LoggerFactory
  * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2014 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2014 Wikimedia Foundation and contributors
  */
 interface Spi {
 
index 9ec15cb..92624a0 100644 (file)
@@ -29,8 +29,7 @@ use Monolog\Formatter\NormalizerFormatter;
  * delegating the formatting to \MediaWiki\Logger\LegacyLogger.
  *
  * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2013 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2013 Wikimedia Foundation and contributors
  * @see \MediaWiki\Logger\LegacyLogger
  */
 class LegacyFormatter extends NormalizerFormatter {
index d40414c..58fca8e 100644 (file)
@@ -44,8 +44,7 @@ use UnexpectedValueException;
  * replacement for \Monolog\Handler\StreamHandler.
  *
  * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2013 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2013 Wikimedia Foundation and contributors
  */
 class LegacyHandler extends AbstractProcessingHandler {
 
index 0ad9b15..5a7ddb1 100644 (file)
@@ -37,8 +37,7 @@ use MWExceptionHandler;
  * will be used to redact the trace information.
  *
  * @since 1.26
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2015 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2015 Wikimedia Foundation and contributors
  */
 class LineFormatter extends MonologLineFormatter {
 
index 104ee58..780ea94 100644 (file)
@@ -43,8 +43,7 @@ use Monolog\Logger;
  * default Logstash syslog input handler.
  *
  * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2015 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2015 Wikimedia Foundation and contributors
  */
 class SyslogHandler extends SyslogUdpHandler {
 
index ad939a0..5e32887 100644 (file)
@@ -25,8 +25,7 @@ namespace MediaWiki\Logger\Monolog;
  * wiki / request ID, and MediaWiki version.
  *
  * @since 1.25
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2013 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2013 Wikimedia Foundation and contributors
  */
 class WikiProcessor {
 
index b0ab244..0b58cc1 100644 (file)
@@ -847,7 +847,7 @@ class DifferenceEngine extends ContextSource {
         * @return bool|string
         */
        public function generateTextDiffBody( $otext, $ntext ) {
-               $diff = function() use ( $otext, $ntext ) {
+               $diff = function () use ( $otext, $ntext ) {
                        $time = microtime( true );
 
                        $result = $this->textDiff( $otext, $ntext );
@@ -867,7 +867,7 @@ class DifferenceEngine extends ContextSource {
                 * @param Status $status
                 * @throws FatalError
                 */
-               $error = function( $status ) {
+               $error = function ( $status ) {
                        throw new FatalError( $status->getWikiText() );
                };
 
index f83fd1c..bcd253f 100644 (file)
@@ -73,7 +73,7 @@ class ForeignDBViaLBRepo extends LocalRepo {
         * @return Closure
         */
        protected function getDBFactory() {
-               return function( $index ) {
+               return function ( $index ) {
                        return wfGetLB( $this->wiki )->getConnectionRef( $index, [], $this->wiki );
                };
        }
index d91ab24..20d51c2 100644 (file)
@@ -483,7 +483,7 @@ class LocalRepo extends FileRepo {
         * @return Closure
         */
        protected function getDBFactory() {
-               return function( $index ) {
+               return function ( $index ) {
                        return wfGetDB( $index );
                };
        }
index e1c2546..a412250 100644 (file)
@@ -593,7 +593,7 @@ class LocalFile extends File {
                if ( $upgrade ) {
                        $this->upgrading = true;
                        // Defer updates unless in auto-commit CLI mode
-                       DeferredUpdates::addCallableUpdate( function() {
+                       DeferredUpdates::addCallableUpdate( function () {
                                $this->upgrading = false; // avoid duplicate updates
                                try {
                                        $this->upgradeRow();
index 089213c..10db90c 100644 (file)
@@ -26,7 +26,7 @@ trait HTMLFormElement {
                        // And it's not needed anymore after infusing, so we don't put it in JS config at all.
                        $this->setAttributes( [ 'data-mw-modules' => implode( ',', $this->modules ) ] );
                }
-               $this->registerConfigCallback( function( &$config ) {
+               $this->registerConfigCallback( function ( &$config ) {
                        if ( $this->hideIf !== null ) {
                                $config['hideIf'] = $this->hideIf;
                        }
index 8829f66..53d1d06 100644 (file)
@@ -23,7 +23,7 @@ class HTMLUsersMultiselectField extends HTMLUserTextField {
 
                $usersArray = explode( "\n", $request->getText( $this->mName ) );
                // Remove empty lines
-               $usersArray = array_values( array_filter( $usersArray, function( $username ) {
+               $usersArray = array_values( array_filter( $usersArray, function ( $username ) {
                        return trim( $username ) !== '';
                } ) );
                return $usersArray;
index 6113573..6c56b3d 100644 (file)
@@ -336,7 +336,7 @@ abstract class DatabaseInstaller {
                $services = \MediaWiki\MediaWikiServices::getInstance();
 
                $connection = $status->value;
-               $services->redefineService( 'DBLoadBalancerFactory', function() use ( $connection ) {
+               $services->redefineService( 'DBLoadBalancerFactory', function () use ( $connection ) {
                        return LBFactorySingle::newFromConnection( $connection );
                } );
        }
index 7028224..168d7ed 100644 (file)
@@ -384,7 +384,7 @@ abstract class Installer {
 
                // make sure we use the installer config as the main config
                $configRegistry = $baseConfig->get( 'ConfigRegistry' );
-               $configRegistry['main'] = function() use ( $installerConfig ) {
+               $configRegistry['main'] = function () use ( $installerConfig ) {
                        return $installerConfig;
                };
 
index c504f35..ea0f1b7 100644 (file)
@@ -356,7 +356,7 @@ class CSSMin {
 
                // Re-insert comments
                $pattern = '/' . CSSMin::PLACEHOLDER . '(\d+)x/';
-               $source = preg_replace_callback( $pattern, function( $match ) use ( &$comments ) {
+               $source = preg_replace_callback( $pattern, function ( $match ) use ( &$comments ) {
                        return $comments[ $match[1] ];
                }, $source );
 
index 4ddb813..21d79dc 100644 (file)
@@ -179,7 +179,7 @@ class HashRing {
                if ( $this->liveRing === null || $this->ejectionNextExpiry <= $now ) {
                        $this->ejectionExpiries = array_filter(
                                $this->ejectionExpiries,
-                               function( $expiry ) use ( $now ) {
+                               function ( $expiry ) use ( $now ) {
                                        return ( $expiry > $now );
                                }
                        );
index c96a8a1..6c47c3c 100644 (file)
@@ -21,8 +21,7 @@
 /**
  * Construct objects from configuration instructions.
  *
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2014 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2014 Wikimedia Foundation and contributors
  */
 class ObjectFactory {
 
index c6da432..2383d2a 100644 (file)
@@ -25,8 +25,7 @@ use RunningStat\RunningStat;
  * <https://github.com/phacility/xhprof>. XHProf can be installed as a PECL
  * package for use with PHP5 (Zend PHP) and is built-in to HHVM 3.3.0.
  *
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2014 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2014 Wikimedia Foundation and contributors
  * @since 1.28
  */
 class XhprofData {
index 53bce33..e374532 100644 (file)
@@ -196,7 +196,7 @@ class FileBackendMultiWrite extends FileBackend {
                                if ( $this->asyncWrites && !$this->hasVolatileSources( $ops ) ) {
                                        // Bind $scopeLock to the callback to preserve locks
                                        DeferredUpdates::addCallableUpdate(
-                                               function() use ( $backend, $realOps, $opts, $scopeLock, $relevantPaths ) {
+                                               function () use ( $backend, $realOps, $opts, $scopeLock, $relevantPaths ) {
                                                        wfDebugLog( 'FileOperationReplication',
                                                                "'{$backend->getName()}' async replication; paths: " .
                                                                FormatJson::encode( $relevantPaths ) );
@@ -508,7 +508,7 @@ class FileBackendMultiWrite extends FileBackend {
                        $realOps = $this->substOpBatchPaths( $ops, $backend );
                        if ( $this->asyncWrites && !$this->hasVolatileSources( $ops ) ) {
                                DeferredUpdates::addCallableUpdate(
-                                       function() use ( $backend, $realOps ) {
+                                       function () use ( $backend, $realOps ) {
                                                $backend->doQuickOperations( $realOps );
                                        }
                                );
@@ -562,7 +562,7 @@ class FileBackendMultiWrite extends FileBackend {
                        $realParams = $this->substOpPaths( $params, $backend );
                        if ( $this->asyncWrites ) {
                                DeferredUpdates::addCallableUpdate(
-                                       function() use ( $backend, $method, $realParams ) {
+                                       function () use ( $backend, $method, $realParams ) {
                                                $backend->$method( $realParams );
                                        }
                                );
index 77c4259..7cd678b 100644 (file)
@@ -475,7 +475,7 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
 
                $lSince = microtime( true ); // lock timestamp
 
-               return new ScopedCallback( function() use ( $key, $lSince, $expiry ) {
+               return new ScopedCallback( function () use ( $key, $lSince, $expiry ) {
                        $latency = .050; // latency skew (err towards keeping lock present)
                        $age = ( microtime( true ) - $lSince + $latency );
                        if ( ( $age + $latency ) >= $expiry ) {
index afeffb3..559c28b 100644 (file)
@@ -1822,8 +1822,10 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 
        /**
-        * @param string $name Table name
-        * @return array (DB name, schema name, table prefix, table name)
+        * Get the table components needed for a query given the currently selected database
+        *
+        * @param string $name Table name in the form of db.schema.table, db.table, or table
+        * @return array (DB name or "" for default, schema name, table prefix, table name)
         */
        protected function qualifiedTableComponents( $name ) {
                # We reverse the explode so that database.table and table both output the correct table.
index e237ef4..8d19bc1 100644 (file)
@@ -527,25 +527,23 @@ abstract class DatabaseMysqlBase extends Database {
        }
 
        public function tableExists( $table, $fname = __METHOD__ ) {
-               $table = $this->tableName( $table, 'raw' );
-               if ( isset( $this->mSessionTempTables[$table] ) ) {
-                       return true; // already known to exist and won't show in SHOW TABLES anyway
-               }
-
                // Split database and table into proper variables as Database::tableName() returns
                // shared tables prefixed with their database, which do not work in SHOW TABLES statements
-               list( $database, $schema, $prefix, $table ) = $this->qualifiedTableComponents( $table );
+               list( $database, , $prefix, $table ) = $this->qualifiedTableComponents( $table );
+               $tableName = "{$prefix}{$table}";
 
-               $table = $prefix . $table;
+               if ( isset( $this->mSessionTempTables[$tableName] ) ) {
+                       return true; // already known to exist and won't show in SHOW TABLES anyway
+               }
 
                // We can't use buildLike() here, because it specifies an escape character
                // other than the backslash, which is the only one supported by SHOW TABLES
-               $encLike = $this->escapeLikeInternal( $table, '\\' );
+               $encLike = $this->escapeLikeInternal( $tableName, '\\' );
 
-               // If the database has been specified (such as for shared tables), add a FROM $database clause
+               // If the database has been specified (such as for shared tables), use "FROM"
                if ( $database !== '' ) {
-                       $database = $this->addIdentifierQuotes( $database );
-                       $query = "SHOW TABLES FROM $database LIKE '$encLike'";
+                       $encDatabase = $this->addIdentifierQuotes( $database );
+                       $query = "SHOW TABLES FROM $encDatabase LIKE '$encLike'";
                } else {
                        $query = "SHOW TABLES LIKE '$encLike'";
                }
index 60b6855..9242414 100644 (file)
@@ -1046,4 +1046,3 @@ class DatabaseSqlite extends Database {
 }
 
 class_alias( DatabaseSqlite::class, 'DatabaseSqlite' );
-
index fd79773..62a078c 100644 (file)
@@ -28,4 +28,3 @@ class DBTransactionError extends DBExpectedError {
 }
 
 class_alias( DBTransactionError::class, 'DBTransactionError' );
-
index 3567204..919f103 100644 (file)
@@ -530,7 +530,7 @@ abstract class LBFactory implements ILBFactory {
                        $prefix
                );
 
-               $this->forEachLB( function( ILoadBalancer $lb ) use ( $prefix ) {
+               $this->forEachLB( function ( ILoadBalancer $lb ) use ( $prefix ) {
                        $lb->setDomainPrefix( $prefix );
                } );
        }
index a8af714..526f120 100644 (file)
@@ -55,7 +55,7 @@ class SamplingStatsdClient extends StatsdClient {
                        $samplingRates = [ '*' => $sampleRate ];
                }
                if ( $samplingRates ) {
-                       array_walk( $data, function( $item ) use ( $samplingRates ) {
+                       array_walk( $data, function ( $item ) use ( $samplingRates ) {
                                /** @var $item StatsdData */
                                foreach ( $samplingRates as $pattern => $rate ) {
                                        if ( fnmatch( $pattern, $item->getKey(), FNM_NOESCAPE ) ) {
index 1b7545a..3249330 100644 (file)
@@ -103,7 +103,7 @@ class VirtualRESTServiceClient {
         * @return array (prefix,VirtualRESTService) or (null,null) if none found
         */
        public function getMountAndService( $path ) {
-               $cmpFunc = function( $a, $b ) {
+               $cmpFunc = function ( $a, $b ) {
                        $al = substr_count( $a, '/' );
                        $bl = substr_count( $b, '/' );
                        if ( $al === $bl ) {
@@ -207,7 +207,7 @@ class VirtualRESTServiceClient {
                }
 
                // Function to get IDs that won't collide with keys in $armoredIndexMap
-               $idFunc = function() use ( &$curUniqueId ) {
+               $idFunc = function () use ( &$curUniqueId ) {
                        return $curUniqueId++;
                };
 
index d26b304..43cb44c 100644 (file)
@@ -38,7 +38,7 @@ class PageDataRequestHandler {
                $parts = explode( '/', $subPage, 2 );
                if ( $parts !== 2 ) {
                        $slot = $parts[0];
-                       if ( $slot === 'main' or $slot === '' ) {
+                       if ( $slot === 'main' || $slot === '' ) {
                                return true;
                        }
                }
index 791330c..4b4d19f 100644 (file)
@@ -176,7 +176,7 @@ class RightsLogFormatter extends LogFormatter {
                        $oldmetadata =& $params['oldmetadata'];
                        // unset old metadata entry to ensure metadata goes at the end of the params array
                        unset( $params['oldmetadata'] );
-                       $params['oldmetadata'] = array_map( function( $index ) use ( $params, $oldmetadata ) {
+                       $params['oldmetadata'] = array_map( function ( $index ) use ( $params, $oldmetadata ) {
                                $result = [ 'group' => $params['4:array:oldgroups'][$index] ];
                                if ( isset( $oldmetadata[$index] ) ) {
                                        $result += $oldmetadata[$index];
@@ -194,7 +194,7 @@ class RightsLogFormatter extends LogFormatter {
                        $newmetadata =& $params['newmetadata'];
                        // unset old metadata entry to ensure metadata goes at the end of the params array
                        unset( $params['newmetadata'] );
-                       $params['newmetadata'] = array_map( function( $index ) use ( $params, $newmetadata ) {
+                       $params['newmetadata'] = array_map( function ( $index ) use ( $params, $newmetadata ) {
                                $result = [ 'group' => $params['5:array:newgroups'][$index] ];
                                if ( isset( $newmetadata[$index] ) ) {
                                        $result += $newmetadata[$index];
index 0e23a88..5c7c7fe 100644 (file)
@@ -3334,7 +3334,7 @@ class WikiPage implements Page, IDBAccessObject {
                HTMLFileCache::clearFileCache( $title );
 
                $revid = $revision ? $revision->getId() : null;
-               DeferredUpdates::addCallableUpdate( function() use ( $title, $revid ) {
+               DeferredUpdates::addCallableUpdate( function () use ( $title, $revid ) {
                        InfoAction::invalidateCache( $title, $revid );
                } );
        }
index c83198f..b0d0e5c 100644 (file)
@@ -6070,7 +6070,7 @@ class Parser {
                $e = new Exception;
                $this->mInParse = $e->getTraceAsString();
 
-               $recursiveCheck = new ScopedCallback( function() {
+               $recursiveCheck = new ScopedCallback( function () {
                        $this->mInParse = false;
                } );
 
index 0ce8087..251da52 100644 (file)
@@ -73,7 +73,7 @@ class ProfilerSectionOnly extends Profiler {
         */
        protected function getFunctionReport() {
                $data = $this->getFunctionStats();
-               usort( $data, function( $a, $b ) {
+               usort( $data, function ( $a, $b ) {
                        if ( $a['real'] === $b['real'] ) {
                                return 0;
                        }
index 1bf4f54..09191ee 100644 (file)
@@ -47,8 +47,7 @@
  * a drop-in replacement for Xhprof. Just change the XHPROF_FLAGS_* constants
  * to TIDEWAYS_FLAGS_*.
  *
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2014 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2014 Wikimedia Foundation and contributors
  * @ingroup Profiler
  * @see Xhprof
  * @see https://php.net/xhprof
@@ -201,7 +200,7 @@ class ProfilerXhprof extends Profiler {
         */
        protected function getFunctionReport() {
                $data = $this->getFunctionStats();
-               usort( $data, function( $a, $b ) {
+               usort( $data, function ( $a, $b ) {
                        if ( $a['real'] === $b['real'] ) {
                                return 0;
                        }
index 39a8a3d..ce262bd 100644 (file)
@@ -378,7 +378,7 @@ class ExtensionProcessor implements Processor {
 
        protected function extractExtensionMessagesFiles( $dir, array $info ) {
                if ( isset( $info['ExtensionMessagesFiles'] ) ) {
-                       $this->globals["wgExtensionMessagesFiles"] += array_map( function( $file ) use ( $dir ) {
+                       $this->globals["wgExtensionMessagesFiles"] += array_map( function ( $file ) use ( $dir ) {
                                return "$dir/$file";
                        }, $info['ExtensionMessagesFiles'] );
                }
index 0c5a67e..eac04a9 100644 (file)
@@ -400,7 +400,7 @@ class ExtensionRegistry {
        protected function processAutoLoader( $dir, array $info ) {
                if ( isset( $info['AutoloadClasses'] ) ) {
                        // Make paths absolute, relative to the JSON file
-                       return array_map( function( $file ) use ( $dir ) {
+                       return array_map( function ( $file ) use ( $dir ) {
                                return "$dir/$file";
                        }, $info['AutoloadClasses'] );
                } else {
index 4473bb2..ac95e7c 100644 (file)
@@ -236,7 +236,7 @@ abstract class SearchEngine {
                if ( $namespaces ) {
                        // Filter namespaces to only keep valid ones
                        $validNs = $this->searchableNamespaces();
-                       $namespaces = array_filter( $namespaces, function( $ns ) use( $validNs ) {
+                       $namespaces = array_filter( $namespaces, function ( $ns ) use( $validNs ) {
                                return $ns < 0 || isset( $validNs[$ns] );
                        } );
                } else {
@@ -464,7 +464,7 @@ abstract class SearchEngine {
                        }
                }
 
-               $ns = array_map( function( $space ) {
+               $ns = array_map( function ( $space ) {
                        return $space == NS_MEDIA ? NS_FILE : $space;
                }, $ns );
 
@@ -550,7 +550,7 @@ abstract class SearchEngine {
         * @return Title[]
         */
        public function extractTitles( SearchSuggestionSet $completionResults ) {
-               return $completionResults->map( function( SearchSuggestion $sugg ) {
+               return $completionResults->map( function ( SearchSuggestion $sugg ) {
                        return $sugg->getSuggestedTitle();
                } );
        }
@@ -564,14 +564,14 @@ abstract class SearchEngine {
        protected function processCompletionResults( $search, SearchSuggestionSet $suggestions ) {
                $search = trim( $search );
                // preload the titles with LinkBatch
-               $titles = $suggestions->map( function( SearchSuggestion $sugg ) {
+               $titles = $suggestions->map( function ( SearchSuggestion $sugg ) {
                        return $sugg->getSuggestedTitle();
                } );
                $lb = new LinkBatch( $titles );
                $lb->setCaller( __METHOD__ );
                $lb->execute();
 
-               $results = $suggestions->map( function( SearchSuggestion $sugg ) {
+               $results = $suggestions->map( function ( SearchSuggestion $sugg ) {
                        return $sugg->getSuggestedTitle()->getPrefixedText();
                } );
 
index caad388..6d54dad 100644 (file)
@@ -180,7 +180,7 @@ class SearchSuggestionSet {
         */
        public static function fromTitles( array $titles ) {
                $score = count( $titles );
-               $suggestions = array_map( function( $title ) use ( &$score ) {
+               $suggestions = array_map( function ( $title ) use ( &$score ) {
                        return SearchSuggestion::fromTitle( $score--, $title );
                }, $titles );
                return new SearchSuggestionSet( $suggestions );
@@ -196,7 +196,7 @@ class SearchSuggestionSet {
         */
        public static function fromStrings( array $titles ) {
                $score = count( $titles );
-               $suggestions = array_map( function( $title ) use ( &$score ) {
+               $suggestions = array_map( function ( $title ) use ( &$score ) {
                        return SearchSuggestion::fromText( $score--, $title );
                }, $titles );
                return new SearchSuggestionSet( $suggestions );
index 882084d..074afe3 100644 (file)
@@ -29,8 +29,7 @@ use UnexpectedValueException;
  * Subclass of UnexpectedValueException that can be annotated with additional
  * data for debug logging.
  *
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2016 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2016 Wikimedia Foundation and contributors
  * @since 1.27
  */
 class MetadataMergeException extends UnexpectedValueException {
index 1145efd..6679098 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Created on Sep 08, 2014
  *
- * Copyright Â© 2014 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2014 Wikimedia Foundation and contributors
  *
  * 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
index f7d7cb2..d3e453a 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Created on Sep 08, 2014
  *
- * Copyright Â© 2014 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright Â© 2014 Wikimedia Foundation and contributors
  *
  * 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
index 9594952..67c14d8 100644 (file)
@@ -456,7 +456,7 @@ class SpecialPage implements MessageLocalizer {
                $searchEngine->setLimitOffset( $limit, $offset );
                $searchEngine->setNamespaces( [] );
                $result = $searchEngine->defaultPrefixSearch( $search );
-               return array_map( function( Title $t ) {
+               return array_map( function ( Title $t ) {
                        return $t->getPrefixedText();
                }, $result );
        }
index 1dd78d7..dfdbb06 100644 (file)
@@ -123,7 +123,7 @@ class SpecialBotPasswords extends FormSpecialPage {
                                        $showGrants
                                ),
                                'default' => array_map(
-                                       function( $g ) {
+                                       function ( $g ) {
                                                return "grant-$g";
                                        },
                                        $this->botPassword->getGrants()
@@ -131,14 +131,14 @@ class SpecialBotPasswords extends FormSpecialPage {
                                'tooltips' => array_combine(
                                        array_map( 'MWGrants::getGrantsLink', $showGrants ),
                                        array_map(
-                                               function( $rights ) use ( $lang ) {
+                                               function ( $rights ) use ( $lang ) {
                                                        return $lang->semicolonList( array_map( 'User::getRightDescription', $rights ) );
                                                },
                                                array_intersect_key( MWGrants::getRightsByGrant(), array_flip( $showGrants ) )
                                        )
                                ),
                                'force-options-on' => array_map(
-                                       function( $g ) {
+                                       function ( $g ) {
                                                return "grant-$g";
                                        },
                                        MWGrants::getHiddenGrants()
index 8eaae4c..bee6a39 100644 (file)
@@ -115,7 +115,7 @@ class SpecialChangeContentModel extends FormSpecialPage {
                                'reason' => [
                                        'type' => 'text',
                                        'name' => 'reason',
-                                       'validation-callback' => function( $reason ) {
+                                       'validation-callback' => function ( $reason ) {
                                                $match = EditPage::matchSummarySpamRegex( $reason );
                                                if ( $match ) {
                                                        return $this->msg( 'spamprotectionmatch', $match )->parse();
index a2b5be4..46d7cf7 100644 (file)
@@ -105,7 +105,7 @@ class MovePageForm extends UnlistedSpecialPage {
                $permErrors = $this->oldTitle->getUserPermissionsErrors( 'move', $user );
                if ( count( $permErrors ) ) {
                        // Auto-block user's IP if the account was "hard" blocked
-                       DeferredUpdates::addCallableUpdate( function() use ( $user ) {
+                       DeferredUpdates::addCallableUpdate( function () use ( $user ) {
                                $user->spreadAnyEditBlock();
                        } );
                        throw new PermissionsError( 'move', $permErrors );
index 37006d8..5878e1f 100644 (file)
@@ -20,7 +20,6 @@
  * @since 1.21
  * @file
  * @ingroup SpecialPage
- * @author Brad Jorsch
  */
 
 /**
index 002b47c..d0a0317 100644 (file)
@@ -344,7 +344,7 @@ class UserrightsPage extends SpecialPage {
                // UNLESS the user can only add this group (not remove it) and the expiry time
                // is being brought forward (T156784)
                $add = array_filter( $add,
-                       function( $group ) use ( $groups, $groupExpiries, $removable, $ugms ) {
+                       function ( $group ) use ( $groups, $groupExpiries, $removable, $ugms ) {
                                if ( isset( $groupExpiries[$group] ) &&
                                        !in_array( $group, $removable ) &&
                                        isset( $ugms[$group] ) &&
@@ -437,12 +437,12 @@ class UserrightsPage extends SpecialPage {
 
                // make sure $oldUGMs and $newUGMs are in the same order, and serialise
                // each UGM object to a simplified array
-               $oldUGMs = array_map( function( $group ) use ( $oldUGMs ) {
+               $oldUGMs = array_map( function ( $group ) use ( $oldUGMs ) {
                        return isset( $oldUGMs[$group] ) ?
                                self::serialiseUgmForLog( $oldUGMs[$group] ) :
                                null;
                }, $oldGroups );
-               $newUGMs = array_map( function( $group ) use ( $newUGMs ) {
+               $newUGMs = array_map( function ( $group ) use ( $newUGMs ) {
                        return isset( $newUGMs[$group] ) ?
                                self::serialiseUgmForLog( $newUGMs[$group] ) :
                                null;
index caa0e1f..30c4a0b 100644 (file)
@@ -511,7 +511,7 @@ class SpecialVersion extends SpecialPage {
                                // in their proper section
                                continue;
                        }
-                       $authors = array_map( function( $arr ) {
+                       $authors = array_map( function ( $arr ) {
                                // If a homepage is set, link to it
                                if ( isset( $arr['homepage'] ) ) {
                                        return "[{$arr['homepage']} {$arr['name']}]";
index 3467b49..b0c12e4 100644 (file)
@@ -1891,7 +1891,7 @@ class Balancer {
                        $bad = array_uintersect_assoc(
                                $this->allowedHtmlElements,
                                BalanceSets::$unsupportedSet[BalanceSets::HTML_NAMESPACE],
-                               function( $a, $b ) {
+                               function ( $a, $b ) {
                                        // Ignore the values (just intersect the keys) by saying
                                        // all values are equal to each other.
                                        return 0;
index 4d16594..52c14f7 100644 (file)
@@ -2506,7 +2506,7 @@ class User implements IDBAccessObject {
                        $cache->delete( $key, 1 );
                } else {
                        wfGetDB( DB_MASTER )->onTransactionPreCommitOrIdle(
-                               function() use ( $cache, $key ) {
+                               function () use ( $cache, $key ) {
                                        $cache->delete( $key );
                                },
                                __METHOD__
@@ -3698,7 +3698,7 @@ class User implements IDBAccessObject {
                        }
 
                        // Try to update the DB post-send and only if needed...
-                       DeferredUpdates::addCallableUpdate( function() use ( $title, $oldid ) {
+                       DeferredUpdates::addCallableUpdate( function () use ( $title, $oldid ) {
                                if ( !$this->getNewtalk() ) {
                                        return; // no notifications to clear
                                }
index 39b65c3..fc8bde9 100644 (file)
@@ -77,7 +77,7 @@ class BatchRowUpdate {
                $this->reader = $reader;
                $this->writer = $writer;
                $this->generator = $generator;
-               $this->output = function() {
+               $this->output = function () {
                }; // nop
        }
 
index dd67fa8..f0ace2c 100644 (file)
@@ -715,4 +715,3 @@ class ZipDirectoryReader {
                }
        }
 }
-
index 5e8e754..9ccf6d6 100644 (file)
@@ -49,4 +49,3 @@ class CodeCleanerGlobalsPass extends \Psy\CodeCleaner\CodeCleanerPass {
                return $nodes;
        }
 }
-
index 9906990..aa1f668 100644 (file)
@@ -8,7 +8,7 @@ class ValidateRegistrationFile extends Maintenance {
                $this->addArg( 'path', 'Path to extension.json/skin.json file.', true );
        }
        public function execute() {
-               $validator = new ExtensionJsonValidator( function( $msg ) {
+               $validator = new ExtensionJsonValidator( function ( $msg ) {
                        $this->error( $msg, 1 );
                } );
                $validator->checkDependencies();
index 440604e..197cc78 100644 (file)
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -38,7 +38,7 @@
                </properties>
        </rule>
        <file>.</file>
-       <arg name="encoding" value="utf8"/>
+       <arg name="encoding" value="UTF-8"/>
        <arg name="extensions" value="php,php5,inc,sample"/>
        <rule ref="Generic.Files.LineLength">
                <exclude-pattern>*/languages/messages/Messages*.php</exclude-pattern>
index c1a936d..2307f30 100644 (file)
@@ -12,6 +12,7 @@
         * @cfg {string} [view='default'] Name of the display group this group
         *  is a part of.
         * @cfg {string} [title] Group title
+        * @cfg {boolean} [hidden] This group is hidden from the regular menu views
         * @cfg {string} [separator='|'] Value separator for 'string_options' groups
         * @cfg {boolean} [active] Group is active
         * @cfg {boolean} [fullCoverage] This filters in this group collectively cover all results
@@ -36,6 +37,7 @@
                this.type = config.type || 'send_unselected_if_any';
                this.view = config.view || 'default';
                this.title = config.title || name;
+               this.hidden = !!config.hidden;
                this.separator = config.separator || '|';
                this.labelPrefixKey = config.labelPrefixKey;
 
                                        return item.getParamName();
                                } )
                        ).join( this.getSeparator() );
+               } else if ( this.getType() === 'single_option' ) {
+                       // For this group, the parameter is the group name,
+                       // and a single item can be selected, or none at all
+                       // The item also must be recognized or none is set as
+                       // default
+                       model.defaultParams[ this.getName() ] = this.getItemByParamName( groupDefault ) ? groupDefault : '';
                }
        };
 
        /**
         * Respond to filterItem update event
         *
+        * @param {mw.rcfilters.dm.FilterItem} item Updated filter item
         * @fires update
         */
-       mw.rcfilters.dm.FilterGroup.prototype.onFilterItemUpdate = function () {
+       mw.rcfilters.dm.FilterGroup.prototype.onFilterItemUpdate = function ( item ) {
                // Update state
-               var active = this.areAnySelected();
+               var active = this.areAnySelected(),
+                       itemName = item && item.getName();
+
+               if ( item.isSelected() && this.getType() === 'single_option' ) {
+                       // Change the selection to only be the newly selected item
+                       this.getItems().forEach( function ( filterItem ) {
+                               if ( filterItem.getName() !== itemName ) {
+                                       filterItem.toggleSelected( false );
+                               }
+                       } );
+               }
 
                if ( this.active !== active ) {
                        this.active = active;
                return this.active;
        };
 
+       /**
+        * Get group hidden state
+        *
+        * @return {boolean} Hidden state
+        */
+       mw.rcfilters.dm.FilterGroup.prototype.isHidden = function () {
+               return this.hidden;
+       };
+
        /**
         * Get group name
         *
                        areAnySelected = false,
                        buildFromCurrentState = !filterRepresentation,
                        result = {},
-                       filterParamNames = {};
+                       model = this,
+                       filterParamNames = {},
+                       getSelectedParameter = function ( filters ) {
+                               var item,
+                                       selected = [];
+
+                               // Find if any are selected
+                               $.each( filters, function ( name, value ) {
+                                       if ( value ) {
+                                               selected.push( name );
+                                       }
+                               } );
+
+                               item = model.getItemByName( selected[ 0 ] );
+                               return ( item && item.getParamName() ) || '';
+                       };
 
                filterRepresentation = filterRepresentation || {};
 
 
                        result[ this.getName() ] = ( values.length === Object.keys( filterRepresentation ).length ) ?
                                'all' : values.join( this.getSeparator() );
+               } else if ( this.getType() === 'single_option' ) {
+                       result[ this.getName() ] = getSelectedParameter( filterRepresentation );
                }
 
                return result;
                                        // Otherwise, the filter is selected only if it appears in the parameter values
                                        paramValues.indexOf( filterItem.getParamName() ) > -1;
                        } );
+               } else if ( this.getType() === 'single_option' ) {
+                       // There is parameter that fits a single filter, or none at all
+                       this.getItems().forEach( function ( filterItem ) {
+                               result[ filterItem.getName() ] = filterItem.getParamName() === paramRepresentation;
+                       } );
                }
 
                // Go over result and make sure all filters are represented.
                return result;
        };
 
+       /**
+        * Get item by its filter name
+        *
+        * @param {string} filterName Filter name
+        * @return {mw.rcfilters.dm.FilterItem} Filter item
+        */
+       mw.rcfilters.dm.FilterGroup.prototype.getItemByName = function ( filterName ) {
+               return this.getItems().filter( function ( item ) {
+                       return item.getName() === filterName;
+               } )[ 0 ];
+       };
+
        /**
         * Get item by its parameter name
         *
index 37cf4dd..75431d9 100644 (file)
                // Collect views
                allViews = {
                        'default': {
-                               label: mw.msg( 'rcfilters-filterlist-title' ),
+                               title: mw.msg( 'rcfilters-filterlist-title' ),
                                groups: filterGroups
                        }
                };
                        viewData.groups.forEach( function ( groupData ) {
                                var group = groupData.name;
 
-                               model.groups[ group ] = new mw.rcfilters.dm.FilterGroup(
-                                       group,
-                                       $.extend( true, {}, groupData, { view: viewName } )
-                               );
+                               if ( !model.groups[ group ] ) {
+                                       model.groups[ group ] = new mw.rcfilters.dm.FilterGroup(
+                                               group,
+                                               $.extend( true, {}, groupData, { view: viewName } )
+                                       );
+                               }
 
                                model.groups[ group ].initializeFilters( groupData.filters, groupData.default );
                                items = items.concat( model.groups[ group ].getItems() );
                                groupModel.getItems().forEach( function ( filterItem ) {
                                        model.parameterMap[ filterItem.getParamName() ] = filterItem;
                                } );
-                       } else if ( groupModel.getType() === 'string_options' ) {
+                       } else if (
+                               groupModel.getType() === 'string_options' ||
+                               groupModel.getType() === 'single_option'
+                       ) {
                                // Group
                                model.parameterMap[ groupModel.getName() ] = groupModel;
                        }
        /**
         * Get the label for the current view
         *
+        * @param {string} viewName View name
         * @return {string} Label for the current view
         */
-       mw.rcfilters.dm.FiltersViewModel.prototype.getCurrentViewLabel = function () {
-               return this.views[ this.getCurrentView() ].title;
+       mw.rcfilters.dm.FiltersViewModel.prototype.getViewTitle = function ( viewName ) {
+               viewName = viewName || this.getCurrentView();
+
+               return this.views[ viewName ] && this.views[ viewName ].title;
        };
 
        /**
index fe91489..0138884 100644 (file)
        mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onModelUpdate = function () {
                var currentView = this.model.getCurrentView();
 
-               this.setLabel( this.model.getCurrentViewLabel() );
+               this.setLabel( this.model.getViewTitle( currentView ) );
 
                this.invertNamespacesButton.toggle( currentView === 'namespaces' );
                this.backButton.toggle( currentView !== 'default' );
index 4e1ae97..2b10cf0 100644 (file)
                        this.$element.find( '.mw-tagfilter-label' ).closest( 'tr' ).detach();
                }
 
+               if ( !this.$element.find( '.mw-recentchanges-table tr' ).length ) {
+                       this.$element.find( 'hr' ).detach();
+               }
+
                // Collapse legend
                // see resources/src/mediawiki.special/mediawiki.special.changelist.legend.js
                this.$element.find( '.mw-changeslist-legend' )
index cc63fb6..c12e10e 100644 (file)
 
                // Count groups per view
                $.each( groups, function ( groupName, groupModel ) {
-                       viewGroupCount[ groupModel.getView() ] = viewGroupCount[ groupModel.getView() ] || 0;
-                       viewGroupCount[ groupModel.getView() ]++;
+                       if ( !groupModel.isHidden() ) {
+                               viewGroupCount[ groupModel.getView() ] = viewGroupCount[ groupModel.getView() ] || 0;
+                               viewGroupCount[ groupModel.getView() ]++;
+                       }
                } );
 
                $.each( groups, function ( groupName, groupModel ) {
                        var currentItems = [],
                                view = groupModel.getView();
 
-                       if ( viewGroupCount[ view ] > 1 ) {
-                               // Only add a section header if there is more than
-                               // one group
-                               currentItems.push(
-                                       // Group section
-                                       new mw.rcfilters.ui.FilterMenuSectionOptionWidget(
-                                               widget.controller,
-                                               groupModel,
-                                               {
-                                                       $overlay: widget.$overlay
-                                               }
-                                       )
-                               );
-                       }
+                       if ( !groupModel.isHidden() ) {
+                               if ( viewGroupCount[ view ] > 1 ) {
+                                       // Only add a section header if there is more than
+                                       // one group
+                                       currentItems.push(
+                                               // Group section
+                                               new mw.rcfilters.ui.FilterMenuSectionOptionWidget(
+                                                       widget.controller,
+                                                       groupModel,
+                                                       {
+                                                               $overlay: widget.$overlay
+                                                       }
+                                               )
+                                       );
+                               }
 
-                       // Add items
-                       widget.model.getGroupFilters( groupName ).forEach( function ( filterItem ) {
-                               currentItems.push(
-                                       new mw.rcfilters.ui.FilterMenuOptionWidget(
-                                               widget.controller,
-                                               filterItem,
-                                               {
-                                                       $overlay: widget.$overlay
-                                               }
-                                       )
-                               );
-                       } );
-
-                       // Cache the items per view, so we can switch between them
-                       // without rebuilding the widgets each time
-                       widget.views[ view ] = widget.views[ view ] || [];
-                       widget.views[ view ] = widget.views[ view ].concat( currentItems );
+                               // Add items
+                               widget.model.getGroupFilters( groupName ).forEach( function ( filterItem ) {
+                                       currentItems.push(
+                                               new mw.rcfilters.ui.FilterMenuOptionWidget(
+                                                       widget.controller,
+                                                       filterItem,
+                                                       {
+                                                               $overlay: widget.$overlay
+                                                       }
+                                               )
+                                       );
+                               } );
+
+                               // Cache the items per view, so we can switch between them
+                               // without rebuilding the widgets each time
+                               widget.views[ view ] = widget.views[ view ] || [];
+                               widget.views[ view ] = widget.views[ view ].concat( currentItems );
+                       }
                } );
 
                this.switchView( this.model.getCurrentView() );
index f44b0d5..3ae3561 100644 (file)
@@ -240,7 +240,7 @@ class ParserTestRunner {
                        'name' => 'nullLockManager',
                        'class' => 'NullLockManager',
                ] ];
-               $reset = function() {
+               $reset = function () {
                        LockManagerGroup::destroySingletons();
                };
                $setup[] = $reset;
@@ -288,7 +288,7 @@ class ParserTestRunner {
                MediaWikiServices::getInstance()->disableService( 'MediaHandlerFactory' );
                MediaWikiServices::getInstance()->redefineService(
                        'MediaHandlerFactory',
-                       function() {
+                       function () {
                                return new MockMediaHandlerFactory();
                        }
                );
@@ -428,7 +428,7 @@ class ParserTestRunner {
         * @return ScopedCallback
         */
        protected function createTeardownObject( $teardown, $nextTeardown = null ) {
-               return new ScopedCallback( function() use ( $teardown, $nextTeardown ) {
+               return new ScopedCallback( function () use ( $teardown, $nextTeardown ) {
                        // Schedule teardown snippets in reverse order
                        $teardown = array_reverse( $teardown );
 
index df3d568..c1ada45 100644 (file)
@@ -309,7 +309,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                ConfigFactory $oldFactory,
                array $configurations
        ) {
-               return function( MediaWikiServices $services ) use ( $oldFactory, $configurations ) {
+               return function ( MediaWikiServices $services ) use ( $oldFactory, $configurations ) {
                        $factory = new ConfigFactory();
 
                        // clone configurations from $oldFactory that are not overwritten by $configurations
index afd80ff..388aee7 100644 (file)
@@ -3,19 +3,19 @@
 class WfArrayFilterTest extends \PHPUnit_Framework_TestCase {
        public function testWfArrayFilter() {
                $arr = [ 'a' => 1, 'b' => 2, 'c' => 3 ];
-               $filtered = wfArrayFilter( $arr, function( $val, $key ) {
+               $filtered = wfArrayFilter( $arr, function ( $val, $key ) {
                        return $key !== 'b';
                } );
                $this->assertSame( [ 'a' => 1, 'c' => 3 ], $filtered );
 
                $arr = [ 'a' => 1, 'b' => 2, 'c' => 3 ];
-               $filtered = wfArrayFilter( $arr, function( $val, $key ) {
+               $filtered = wfArrayFilter( $arr, function ( $val, $key ) {
                        return $val !== 2;
                } );
                $this->assertSame( [ 'a' => 1, 'c' => 3 ], $filtered );
 
                $arr = [ 'a', 'b', 'c' ];
-               $filtered = wfArrayFilter( $arr, function( $val, $key ) {
+               $filtered = wfArrayFilter( $arr, function ( $val, $key ) {
                        return $key !== 0;
                } );
                $this->assertSame( [ 1 => 'b',  2 => 'c' ], $filtered );
@@ -23,13 +23,13 @@ class WfArrayFilterTest extends \PHPUnit_Framework_TestCase {
 
        public function testWfArrayFilterByKey() {
                $arr = [ 'a' => 1, 'b' => 2, 'c' => 3 ];
-               $filtered = wfArrayFilterByKey( $arr, function( $key ) {
+               $filtered = wfArrayFilterByKey( $arr, function ( $key ) {
                        return $key !== 'b';
                } );
                $this->assertSame( [ 'a' => 1, 'c' => 3 ], $filtered );
 
                $arr = [ 'a', 'b', 'c' ];
-               $filtered = wfArrayFilterByKey( $arr, function( $key ) {
+               $filtered = wfArrayFilterByKey( $arr, function ( $key ) {
                        return $key !== 0;
                } );
                $this->assertSame( [ 1 => 'b',  2 => 'c' ], $filtered );
index 3edf99f..2ca5935 100644 (file)
@@ -385,21 +385,21 @@ class LinkerTest extends MediaWikiLangTestCase {
                return [
                        // Override $html
                        [
-                               function( $dummy, $title, $options, &$html, &$attribs, &$ret ) {
+                               function ( $dummy, $title, $options, &$html, &$attribs, &$ret ) {
                                        $html = 'foobar';
                                },
                                '<a href="/wiki/Special:BlankPage" title="Special:BlankPage">foobar</a>'
                        ],
                        // Modify $attribs
                        [
-                               function( $dummy, $title, $options, &$html, &$attribs, &$ret ) {
+                               function ( $dummy, $title, $options, &$html, &$attribs, &$ret ) {
                                        $attribs['bar'] = 'baz';
                                },
                                '<a href="/wiki/Special:BlankPage" title="Special:BlankPage" bar="baz">Special:BlankPage</a>'
                        ],
                        // Fully override return value and abort hook
                        [
-                               function( $dummy, $title, $options, &$html, &$attribs, &$ret ) {
+                               function ( $dummy, $title, $options, &$html, &$attribs, &$ret ) {
                                        $ret = 'blahblahblah';
                                        return false;
                                },
index 037faa6..b4e9626 100644 (file)
@@ -77,7 +77,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
 
                $newServices->defineService(
                        'Test',
-                       function() use ( $service1 ) {
+                       function () use ( $service1 ) {
                                return $service1;
                        }
                );
@@ -121,7 +121,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
 
                $newServices->defineService(
                        'Test',
-                       function() use ( &$instantiatorReturnValues ) {
+                       function () use ( &$instantiatorReturnValues ) {
                                return array_shift( $instantiatorReturnValues );
                        }
                );
@@ -150,7 +150,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
 
                $newServices->redefineService(
                        'DBLoadBalancerFactory',
-                       function() use ( $lbFactory ) {
+                       function () use ( $lbFactory ) {
                                return $lbFactory;
                        }
                );
@@ -194,7 +194,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
 
                $newServices->defineService(
                        'Test',
-                       function() use ( &$instantiatorReturnValues ) {
+                       function () use ( &$instantiatorReturnValues ) {
                                return array_shift( $instantiatorReturnValues );
                        }
                );
@@ -217,7 +217,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
 
                $services->defineService(
                        'Test',
-                       function() use ( &$serviceCounter ) {
+                       function () use ( &$serviceCounter ) {
                                $serviceCounter++;
                                $service = $this->createMock( 'MediaWiki\Services\DestructibleService' );
                                $service->expects( $this->once() )->method( 'destroy' );
@@ -247,7 +247,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
 
                $services->defineService(
                        'Test',
-                       function() {
+                       function () {
                                $service = $this->createMock( 'MediaWiki\Services\DestructibleService' );
                                $service->expects( $this->never() )->method( 'destroy' );
                                return $service;
index 617e39c..b68ee48 100644 (file)
@@ -20,7 +20,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $this->assertEmpty( $names );
 
                $name = 'TestService92834576';
-               $services->defineService( $name, function() {
+               $services->defineService( $name, function () {
                        return null;
                } );
 
@@ -34,7 +34,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $name = 'TestService92834576';
                $this->assertFalse( $services->hasService( $name ) );
 
-               $services->defineService( $name, function() {
+               $services->defineService( $name, function () {
                        return null;
                } );
 
@@ -50,7 +50,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
 
                $services->defineService(
                        $name,
-                       function( $actualLocator, $extra ) use ( $services, $theService, &$count ) {
+                       function ( $actualLocator, $extra ) use ( $services, $theService, &$count ) {
                                $count++;
                                PHPUnit_Framework_Assert::assertSame( $services, $actualLocator );
                                PHPUnit_Framework_Assert::assertSame( $extra, 'Foo' );
@@ -79,14 +79,14 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
 
                $services->defineService(
                        'Foo',
-                       function() {
+                       function () {
                                return new stdClass();
                        }
                );
 
                $services->defineService(
                        'Bar',
-                       function() {
+                       function () {
                                return new stdClass();
                        }
                );
@@ -122,7 +122,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $theService = new stdClass();
                $name = 'TestService92834576';
 
-               $services->defineService( $name, function( $actualLocator ) use ( $services, $theService ) {
+               $services->defineService( $name, function ( $actualLocator ) use ( $services, $theService ) {
                        PHPUnit_Framework_Assert::assertSame( $services, $actualLocator );
                        return $theService;
                } );
@@ -137,13 +137,13 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $theService = new stdClass();
                $name = 'TestService92834576';
 
-               $services->defineService( $name, function() use ( $theService ) {
+               $services->defineService( $name, function () use ( $theService ) {
                        return $theService;
                } );
 
                $this->setExpectedException( 'MediaWiki\Services\ServiceAlreadyDefinedException' );
 
-               $services->defineService( $name, function() use ( $theService ) {
+               $services->defineService( $name, function () use ( $theService ) {
                        return $theService;
                } );
        }
@@ -152,10 +152,10 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $services = $this->newServiceContainer();
 
                $wiring = [
-                       'Foo' => function() {
+                       'Foo' => function () {
                                return 'Foo!';
                        },
-                       'Bar' => function() {
+                       'Bar' => function () {
                                return 'Bar!';
                        },
                ];
@@ -170,13 +170,13 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $services = $this->newServiceContainer();
 
                $wiring = [
-                       'Foo' => function() {
+                       'Foo' => function () {
                                return 'Foo!';
                        },
-                       'Bar' => function() {
+                       'Bar' => function () {
                                return 'Bar!';
                        },
-                       'Car' => function() {
+                       'Car' => function () {
                                return 'FUBAR!';
                        },
                ];
@@ -187,7 +187,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
 
                // define a service before importing, so we can later check that
                // existing service instances survive importWiring()
-               $newServices->defineService( 'Car', function() {
+               $newServices->defineService( 'Car', function () {
                        return 'Car!';
                } );
 
@@ -196,7 +196,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
 
                // Define another service, so we can later check that extra wiring
                // is not lost.
-               $newServices->defineService( 'Xar', function() {
+               $newServices->defineService( 'Xar', function () {
                        return 'Xar!';
                } );
 
@@ -249,7 +249,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $theService1 = new stdClass();
                $name = 'TestService92834576';
 
-               $services->defineService( $name, function() {
+               $services->defineService( $name, function () {
                        PHPUnit_Framework_Assert::fail(
                                'The original instantiator function should not get called'
                        );
@@ -258,7 +258,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                // redefine before instantiation
                $services->redefineService(
                        $name,
-                       function( $actualLocator, $extra ) use ( $services, $theService1 ) {
+                       function ( $actualLocator, $extra ) use ( $services, $theService1 ) {
                                PHPUnit_Framework_Assert::assertSame( $services, $actualLocator );
                                PHPUnit_Framework_Assert::assertSame( 'Foo', $extra );
                                return $theService1;
@@ -275,14 +275,14 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $theService1 = new stdClass();
                $name = 'TestService92834576';
 
-               $services->defineService( $name, function() {
+               $services->defineService( $name, function () {
                        return 'Foo';
                } );
 
                // disable the service. we should be able to redefine it anyway.
                $services->disableService( $name );
 
-               $services->redefineService( $name, function() use ( $theService1 ) {
+               $services->redefineService( $name, function () use ( $theService1 ) {
                        return $theService1;
                } );
 
@@ -298,7 +298,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
 
                $this->setExpectedException( 'MediaWiki\Services\NoSuchServiceException' );
 
-               $services->redefineService( $name, function() use ( $theService ) {
+               $services->redefineService( $name, function () use ( $theService ) {
                        return $theService;
                } );
        }
@@ -309,7 +309,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $theService = new stdClass();
                $name = 'TestService92834576';
 
-               $services->defineService( $name, function() {
+               $services->defineService( $name, function () {
                        return 'Foo';
                } );
 
@@ -318,7 +318,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
 
                $this->setExpectedException( 'MediaWiki\Services\CannotReplaceActiveServiceException' );
 
-               $services->redefineService( $name, function() use ( $theService ) {
+               $services->redefineService( $name, function () use ( $theService ) {
                        return $theService;
                } );
        }
@@ -331,13 +331,13 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $destructible->expects( $this->once() )
                        ->method( 'destroy' );
 
-               $services->defineService( 'Foo', function() use ( $destructible ) {
+               $services->defineService( 'Foo', function () use ( $destructible ) {
                        return $destructible;
                } );
-               $services->defineService( 'Bar', function() {
+               $services->defineService( 'Bar', function () {
                        return new stdClass();
                } );
-               $services->defineService( 'Qux', function() {
+               $services->defineService( 'Qux', function () {
                        return new stdClass();
                } );
 
@@ -377,7 +377,7 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
 
                $this->setExpectedException( 'MediaWiki\Services\NoSuchServiceException' );
 
-               $services->redefineService( $name, function() use ( $theService ) {
+               $services->redefineService( $name, function () use ( $theService ) {
                        return $theService;
                } );
        }
@@ -390,11 +390,11 @@ class ServiceContainerTest extends PHPUnit_Framework_TestCase {
                $destructible->expects( $this->once() )
                        ->method( 'destroy' );
 
-               $services->defineService( 'Foo', function() use ( $destructible ) {
+               $services->defineService( 'Foo', function () use ( $destructible ) {
                        return $destructible;
                } );
 
-               $services->defineService( 'Bar', function() {
+               $services->defineService( 'Bar', function () {
                        return new stdClass();
                } );
 
index 186021a..b6ff4eb 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 return [
-       'Foo' => function() {
+       'Foo' => function () {
                return 'Foo!';
        },
 ];
index 3b4fff0..dfff64f 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 return [
-       'Bar' => function() {
+       'Bar' => function () {
                return 'Bar!';
        },
 ];
index 84a6adf..21d1bf2 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Testing logger
  *
- * Copyright (C) 2015 Brad Jorsch <bjorsch@wikimedia.org>
+ * Copyright (C) 2015 Wikimedia Foundation and contributors
  *
  * 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
@@ -20,7 +20,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  *
  * @file
- * @author Brad Jorsch <bjorsch@wikimedia.org>
  */
 
 use Psr\Log\LogLevel;
index 872c580..6b436a8 100644 (file)
@@ -21,9 +21,9 @@ class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
                                $this->isType( 'array' ),
                                $this->isType( 'int' )
                        )
-                       ->will( $this->returnCallback( function( $a, $conj ) {
+                       ->will( $this->returnCallback( function ( $a, $conj ) {
                                $sqlConj = $conj === LIST_AND ? ' AND ' : ' OR ';
-                               return join( $sqlConj, array_map( function( $s ) {
+                               return join( $sqlConj, array_map( function ( $s ) {
                                        return '(' . $s . ')';
                                }, $a
                                ) );
@@ -31,7 +31,7 @@ class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
 
                $mock->expects( $this->any() )
                        ->method( 'addQuotes' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return "'$value'";
                        } ) );
 
@@ -41,7 +41,7 @@ class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
 
                $mock->expects( $this->any() )
                        ->method( 'bitAnd' )
-                       ->willReturnCallback( function( $a, $b ) {
+                       ->willReturnCallback( function ( $a, $b ) {
                                return "($a & $b)";
                        } );
 
@@ -106,12 +106,12 @@ class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
 
                $mock->expects( $this->any() )
                        ->method( 'isAllowed' )
-                       ->will( $this->returnCallback( function( $action ) use ( $notAllowedAction ) {
+                       ->will( $this->returnCallback( function ( $action ) use ( $notAllowedAction ) {
                                return $action !== $notAllowedAction;
                        } ) );
                $mock->expects( $this->any() )
                        ->method( 'isAllowedAny' )
-                       ->will( $this->returnCallback( function() use ( $notAllowedAction ) {
+                       ->will( $this->returnCallback( function () use ( $notAllowedAction ) {
                                $actions = func_get_args();
                                return !in_array( $notAllowedAction, $actions );
                        } ) );
@@ -1450,7 +1450,7 @@ class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->any() )
                        ->method( 'addQuotes' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return "'$value'";
                        } ) );
                $mockDb->expects( $this->any() )
@@ -1459,9 +1459,9 @@ class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
                                $this->isType( 'array' ),
                                $this->isType( 'int' )
                        )
-                       ->will( $this->returnCallback( function( $a, $conj ) {
+                       ->will( $this->returnCallback( function ( $a, $conj ) {
                                $sqlConj = $conj === LIST_AND ? ' AND ' : ' OR ';
-                               return join( $sqlConj, array_map( function( $s ) {
+                               return join( $sqlConj, array_map( function ( $s ) {
                                        return '(' . $s . ')';
                                }, $a
                                ) );
index f31028d..fa81eb1 100644 (file)
@@ -48,7 +48,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                        ->getMock();
                $mock->expects( $this->any() )
                        ->method( 'makeKey' )
-                       ->will( $this->returnCallback( function() {
+                       ->will( $this->returnCallback( function () {
                                return implode( ':', func_get_args() );
                        } ) );
                return $mock;
@@ -313,12 +313,12 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                        ->will( $this->returnValue( 7 ) );
                $mockDb->expects( $this->exactly( 1 ) )
                        ->method( 'addQuotes' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return "'$value'";
                        } ) );
                $mockDb->expects( $this->exactly( 1 ) )
                        ->method( 'timestamp' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return 'TS' . $value . 'TS';
                        } ) );
 
@@ -351,12 +351,12 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->exactly( 2 * 3 ) )
                        ->method( 'addQuotes' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return "'$value'";
                        } ) );
                $mockDb->expects( $this->exactly( 3 ) )
                        ->method( 'timestamp' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return 'TS' . $value . 'TS';
                        } ) );
                $mockDb->expects( $this->any() )
@@ -365,9 +365,9 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                                $this->isType( 'array' ),
                                $this->isType( 'int' )
                        )
-                       ->will( $this->returnCallback( function( $a, $conj ) {
+                       ->will( $this->returnCallback( function ( $a, $conj ) {
                                $sqlConj = $conj === LIST_AND ? ' AND ' : ' OR ';
-                               return join( $sqlConj, array_map( function( $s ) {
+                               return join( $sqlConj, array_map( function ( $s ) {
                                        return '(' . $s . ')';
                                }, $a
                                ) );
@@ -446,12 +446,12 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->exactly( 2 * 3 ) )
                        ->method( 'addQuotes' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return "'$value'";
                        } ) );
                $mockDb->expects( $this->exactly( 3 ) )
                        ->method( 'timestamp' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return 'TS' . $value . 'TS';
                        } ) );
                $mockDb->expects( $this->any() )
@@ -460,9 +460,9 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                                $this->isType( 'array' ),
                                $this->isType( 'int' )
                        )
-                       ->will( $this->returnCallback( function( $a, $conj ) {
+                       ->will( $this->returnCallback( function ( $a, $conj ) {
                                $sqlConj = $conj === LIST_AND ? ' AND ' : ' OR ';
-                               return join( $sqlConj, array_map( function( $s ) {
+                               return join( $sqlConj, array_map( function ( $s ) {
                                        return '(' . $s . ')';
                                }, $a
                                ) );
@@ -1970,7 +1970,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
                // Note: This does not actually assert the job is correct
                $callableCallCounter = 0;
-               $mockCallback = function( $callable ) use ( &$callableCallCounter ) {
+               $mockCallback = function ( $callable ) use ( &$callableCallCounter ) {
                        $callableCallCounter++;
                        $this->assertInternalType( 'callable', $callable );
                };
@@ -2011,7 +2011,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
                // Note: This does not actually assert the job is correct
                $callableCallCounter = 0;
-               $mockCallback = function( $callable ) use ( &$callableCallCounter ) {
+               $mockCallback = function ( $callable ) use ( &$callableCallCounter ) {
                        $callableCallCounter++;
                        $this->assertInternalType( 'callable', $callable );
                };
@@ -2105,13 +2105,13 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
                $callableCallCounter = 0;
                $scopedOverride = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
-                       function( $callable ) use ( &$callableCallCounter, $title, $user ) {
+                       function ( $callable ) use ( &$callableCallCounter, $title, $user ) {
                                $callableCallCounter++;
                                $this->verifyCallbackJob(
                                        $callable,
                                        $title,
                                        $user->getId(),
-                                       function( $time ) {
+                                       function ( $time ) {
                                                return $time === null;
                                        }
                                );
@@ -2172,13 +2172,13 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
                $addUpdateCallCounter = 0;
                $scopedOverrideDeferred = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
-                       function( $callable ) use ( &$addUpdateCallCounter, $title, $user ) {
+                       function ( $callable ) use ( &$addUpdateCallCounter, $title, $user ) {
                                $addUpdateCallCounter++;
                                $this->verifyCallbackJob(
                                        $callable,
                                        $title,
                                        $user->getId(),
-                                       function( $time ) {
+                                       function ( $time ) {
                                                return $time !== null && $time > '20151212010101';
                                        }
                                );
@@ -2187,7 +2187,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
                $getTimestampCallCounter = 0;
                $scopedOverrideRevision = $store->overrideRevisionGetTimestampFromIdCallback(
-                       function( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) {
+                       function ( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) {
                                $getTimestampCallCounter++;
                                $this->assertEquals( $title, $titleParam );
                                $this->assertEquals( $oldid, $oldidParam );
@@ -2248,13 +2248,13 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
                $callableCallCounter = 0;
                $scopedOverride = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
-                       function( $callable ) use ( &$callableCallCounter, $title, $user ) {
+                       function ( $callable ) use ( &$callableCallCounter, $title, $user ) {
                                $callableCallCounter++;
                                $this->verifyCallbackJob(
                                        $callable,
                                        $title,
                                        $user->getId(),
-                                       function( $time ) {
+                                       function ( $time ) {
                                                return $time === null;
                                        }
                                );
@@ -2315,13 +2315,13 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
                $addUpdateCallCounter = 0;
                $scopedOverrideDeferred = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
-                       function( $callable ) use ( &$addUpdateCallCounter, $title, $user ) {
+                       function ( $callable ) use ( &$addUpdateCallCounter, $title, $user ) {
                                $addUpdateCallCounter++;
                                $this->verifyCallbackJob(
                                        $callable,
                                        $title,
                                        $user->getId(),
-                                       function( $time ) {
+                                       function ( $time ) {
                                                return $time === '30151212010101';
                                        }
                                );
@@ -2330,7 +2330,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
                $getTimestampCallCounter = 0;
                $scopedOverrideRevision = $store->overrideRevisionGetTimestampFromIdCallback(
-                       function( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) {
+                       function ( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) {
                                $getTimestampCallCounter++;
                                $this->assertEquals( $title, $titleParam );
                                $this->assertEquals( $oldid, $oldidParam );
@@ -2393,13 +2393,13 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
                $addUpdateCallCounter = 0;
                $scopedOverrideDeferred = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
-                       function( $callable ) use ( &$addUpdateCallCounter, $title, $user ) {
+                       function ( $callable ) use ( &$addUpdateCallCounter, $title, $user ) {
                                $addUpdateCallCounter++;
                                $this->verifyCallbackJob(
                                        $callable,
                                        $title,
                                        $user->getId(),
-                                       function( $time ) {
+                                       function ( $time ) {
                                                return $time === false;
                                        }
                                );
@@ -2408,7 +2408,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
 
                $getTimestampCallCounter = 0;
                $scopedOverrideRevision = $store->overrideRevisionGetTimestampFromIdCallback(
-                       function( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) {
+                       function ( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) {
                                $getTimestampCallCounter++;
                                $this->assertEquals( $title, $titleParam );
                                $this->assertEquals( $oldid, $oldidParam );
@@ -2454,7 +2454,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                        ->will( $this->returnValue( true ) );
                $mockDb->expects( $this->exactly( 1 ) )
                        ->method( 'timestamp' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return 'TS' . $value . 'TS';
                        } ) );
 
@@ -2484,7 +2484,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                        ->will( $this->returnValue( true ) );
                $mockDb->expects( $this->exactly( 0 ) )
                        ->method( 'timestamp' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return 'TS' . $value . 'TS';
                        } ) );
 
@@ -2515,7 +2515,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                        ->will( $this->returnValue( true ) );
                $mockDb->expects( $this->exactly( 1 ) )
                        ->method( 'timestamp' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return 'TS' . $value . 'TS';
                        } ) );
                $mockDb->expects( $this->once() )
index 8a2146a..1aa0a13 100644 (file)
@@ -14,7 +14,7 @@ class ApiPageSetTest extends ApiTestCase {
                        ],
 
                        'A simple merge policy adds the redirect data in' => [
-                               function( $current, $new ) {
+                               function ( $current, $new ) {
                                        if ( !isset( $current['index'] ) || $new['index'] < $current['index'] ) {
                                                $current['index'] = $new['index'];
                                        }
index b508928..4f4453f 100644 (file)
@@ -210,7 +210,7 @@ class ApiQueryWatchlistIntegrationTest extends ApiTestCase {
 
                // not checking values of all keys of the actual item, so removing unwanted keys from comparison
                $actualItemsOnlyComparedValues = array_map(
-                       function( array $item ) use ( $keysUsedInValueComparison ) {
+                       function ( array $item ) use ( $keysUsedInValueComparison ) {
                                return array_intersect_key( $item, array_flip( $keysUsedInValueComparison ) );
                        },
                        $actualItems
index d5c17ee..50a59f9 100644 (file)
@@ -87,7 +87,7 @@ class RandomImageGenerator {
                                        __DIR__ . '/words.txt'
                                ] as $dictionaryFile
                        ) {
-                               if ( is_file( $dictionaryFile ) and is_readable( $dictionaryFile ) ) {
+                               if ( is_file( $dictionaryFile ) && is_readable( $dictionaryFile ) ) {
                                        $this->dictionaryFile = $dictionaryFile;
                                        break;
                                }
index 8a76618..ba38128 100644 (file)
@@ -63,7 +63,7 @@ class ConfigFactoryTest extends MediaWikiTestCase {
                // define new config instance
                $newFactory = new ConfigFactory();
                $newFactory->register( 'foo', 'GlobalVarConfig::newInstance' );
-               $newFactory->register( 'bar', function() {
+               $newFactory->register( 'bar', function () {
                        return new HashConfig();
                } );
 
index 403bee1..ee79ffa 100644 (file)
@@ -28,7 +28,7 @@ class ContentHandlerTest extends MediaWikiTestCase {
                                CONTENT_MODEL_CSS => 'CssContentHandler',
                                CONTENT_MODEL_TEXT => 'TextContentHandler',
                                'testing' => 'DummyContentHandlerForTesting',
-                               'testing-callbacks' => function( $modelId ) {
+                               'testing-callbacks' => function ( $modelId ) {
                                        return new DummyContentHandlerForTesting( $modelId );
                                }
                        ],
@@ -418,7 +418,7 @@ class ContentHandlerTest extends MediaWikiTestCase {
 
                $searchEngine->expects( $this->any() )
                        ->method( 'makeSearchFieldMapping' )
-                       ->will( $this->returnCallback( function( $name, $type ) {
+                       ->will( $this->returnCallback( function ( $name, $type ) {
                                        return new DummySearchIndexFieldDefinition( $name, $type );
                        } ) );
 
index f61569a..3dc810c 100644 (file)
  *
  * @file
  * @author Antoine Musso
- * @author Bryan Davis
  * @copyright Â© 2013 Antoine Musso
- * @copyright Â© 2013 Bryan Davis
- * @copyright Â© 2013 Wikimedia Foundation Inc.
+ * @copyright Â© 2013 Wikimedia Foundation and contributors
  */
 
 use Wikimedia\Rdbms\TransactionProfiler;
index 00c47c8..6723a0b 100644 (file)
@@ -112,7 +112,7 @@ class JobTest extends MediaWikiTestCase {
        public function provideTestJobFactory() {
                return [
                        'class name' => [ 'NullJob' ],
-                       'closure' => [ function( Title $title, array $params ) {
+                       'closure' => [ function ( Title $title, array $params ) {
                                return new NullJob( $title, $params );
                        } ],
                        'function' => [ [ $this, 'newNullJob' ] ],
index 5e1970b..cba2939 100644 (file)
@@ -17,7 +17,7 @@ class DeferredStringifierTest extends PHPUnit_Framework_TestCase {
                        // No args
                        [
                                [
-                                       function() {
+                                       function () {
                                                return 'foo';
                                        }
                                ],
@@ -26,7 +26,7 @@ class DeferredStringifierTest extends PHPUnit_Framework_TestCase {
                        // Has args
                        [
                                [
-                                       function( $i ) {
+                                       function ( $i ) {
                                                return $i;
                                        },
                                        'bar'
@@ -41,7 +41,7 @@ class DeferredStringifierTest extends PHPUnit_Framework_TestCase {
         * it is never converted to a string
         */
        public function testCallbackNotCalled() {
-               $ds = new DeferredStringifier( function() {
+               $ds = new DeferredStringifier( function () {
                        throw new Exception( 'This should not be reached!' );
                } );
                // No exception was thrown
index 3e0a61e..35a7b60 100644 (file)
@@ -27,13 +27,13 @@ class ObjectFactoryTest extends PHPUnit_Framework_TestCase {
                $obj = ObjectFactory::getObjectFromSpec( [
                        'class' => 'ObjectFactoryTestFixture',
                        'args' => [
-                               function() {
+                               function () {
                                        return 'wrapped';
                                },
                                'unwrapped',
                        ],
                        'calls' => [
-                               'setter' => [ function() {
+                               'setter' => [ function () {
                                        return 'wrapped';
                                }, ],
                        ],
@@ -54,13 +54,13 @@ class ObjectFactoryTest extends PHPUnit_Framework_TestCase {
                $obj = ObjectFactory::getObjectFromSpec( [
                        'class' => 'ObjectFactoryTestFixture',
                        'args' => [
-                               function() {
+                               function () {
                                        return 'wrapped';
                                },
                                'unwrapped',
                        ],
                        'calls' => [
-                               'setter' => [ function() {
+                               'setter' => [ function () {
                                        return 'wrapped';
                                }, ],
                        ],
@@ -74,11 +74,11 @@ class ObjectFactoryTest extends PHPUnit_Framework_TestCase {
 
                $obj = ObjectFactory::getObjectFromSpec( [
                        'class' => 'ObjectFactoryTestFixture',
-                       'args' => [ function() {
+                       'args' => [ function () {
                                return 'unwrapped';
                        }, ],
                        'calls' => [
-                               'setter' => [ function() {
+                               'setter' => [ function () {
                                        return 'unwrapped';
                                }, ],
                        ],
index a0fb563..35e9005 100644 (file)
@@ -21,8 +21,7 @@
 /**
  * @uses XhprofData
  * @uses AutoLoader
- * @author Bryan Davis <bd808@wikimedia.org>
- * @copyright Â© 2014 Bryan Davis and Wikimedia Foundation.
+ * @copyright Â© 2014 Wikimedia Foundation and contributors
  * @since 1.25
  */
 class XhprofDataTest extends PHPUnit_Framework_TestCase {
index 7f9a772..5c5eeaa 100644 (file)
@@ -66,7 +66,7 @@ XML;
                        null,
                        false,
                        [
-                               'processing_instruction_handler' => function() use ( &$called ) {
+                               'processing_instruction_handler' => function () use ( &$called ) {
                                        $called = true;
                                }
                        ]
index 2b04366..3d405fa 100644 (file)
@@ -176,7 +176,7 @@ class WANObjectCacheTest extends PHPUnit_Framework_TestCase  {
                $priorValue = null;
                $priorAsOf = null;
                $wasSet = 0;
-               $func = function( $old, &$ttl, &$opts, $asOf )
+               $func = function ( $old, &$ttl, &$opts, $asOf )
                use ( &$wasSet, &$priorValue, &$priorAsOf, $value )
                {
                        ++$wasSet;
@@ -583,7 +583,7 @@ class WANObjectCacheTest extends PHPUnit_Framework_TestCase  {
                $value = wfRandomString();
 
                $calls = 0;
-               $func = function() use ( &$calls, $value, $cache, $key ) {
+               $func = function () use ( &$calls, $value, $cache, $key ) {
                        ++$calls;
                        // Immediately kill any mutex rather than waiting a second
                        $cache->delete( $cache::MUTEX_KEY_PREFIX . $key );
@@ -625,7 +625,7 @@ class WANObjectCacheTest extends PHPUnit_Framework_TestCase  {
                $value = wfRandomString();
 
                $calls = 0;
-               $func = function( $oldValue, &$ttl, &$setOpts ) use ( &$calls, $value, $cache, $key ) {
+               $func = function ( $oldValue, &$ttl, &$setOpts ) use ( &$calls, $value, $cache, $key ) {
                        ++$calls;
                        $setOpts['since'] = microtime( true ) - 10;
                        // Immediately kill any mutex rather than waiting a second
@@ -659,7 +659,7 @@ class WANObjectCacheTest extends PHPUnit_Framework_TestCase  {
                $busyValue = wfRandomString();
 
                $calls = 0;
-               $func = function() use ( &$calls, $value, $cache, $key ) {
+               $func = function () use ( &$calls, $value, $cache, $key ) {
                        ++$calls;
                        // Immediately kill any mutex rather than waiting a second
                        $cache->delete( $cache::MUTEX_KEY_PREFIX . $key );
@@ -921,7 +921,7 @@ class WANObjectCacheTest extends PHPUnit_Framework_TestCase  {
                $value = wfRandomString();
 
                $wasSet = 0;
-               $func = function( $old, &$ttl ) use ( &$wasSet, $value ) {
+               $func = function ( $old, &$ttl ) use ( &$wasSet, $value ) {
                        ++$wasSet;
                        return $value;
                };
index 7d12e59..9750ea4 100644 (file)
@@ -41,6 +41,12 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
                                ]
                        ],
 
+                       'htmlTemplateUnknown' => $base + [
+                               'templates' => [
+                                       'templates/notfound.html',
+                               ]
+                       ],
+
                        'aliasedHtmlTemplateModule' => $base + [
                                'templates' => [
                                        'foo.html' => 'templates/template.html',
@@ -259,6 +265,10 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
                                        'bar.html' => "<div>goodbye</div>\n",
                                ],
                        ],
+                       [
+                               $modules['htmlTemplateUnknown'],
+                               false,
+                       ],
                ];
        }
 
@@ -270,9 +280,17 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
                $rl = new ResourceLoaderFileModule( $module );
                $rl->setName( 'testing' );
 
-               $this->assertEquals( $rl->getTemplates(), $expected );
+               if ( $expected === false ) {
+                       $this->setExpectedException( MWException::class );
+                       $rl->getTemplates();
+               } else {
+                       $this->assertEquals( $rl->getTemplates(), $expected );
+               }
        }
 
+       /**
+        * @covers ResourceLoaderFileModule::stripBom
+        */
        public function testBomConcatenation() {
                $basePath = __DIR__ . '/../../data/css';
                $testModule = new ResourceLoaderFileModule( [
index 79d0784..f00253b 100644 (file)
@@ -199,7 +199,7 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
         * @covers ResourceLoader::getModule
         */
        public function testGetModuleFactory() {
-               $factory = function( array $info ) {
+               $factory = function ( array $info ) {
                        $this->assertArrayHasKey( 'kitten', $info );
                        return new ResourceLoaderTestModule( $info );
                };
@@ -607,6 +607,8 @@ mw.example();
         * Verify that when building module content in a load.php response,
         * an exception from one module will not break script output from
         * other modules.
+        *
+        * @covers ResourceLoader::makeModuleResponse
         */
        public function testMakeModuleResponseError() {
                $modules = [
@@ -643,6 +645,8 @@ mw.example();
         * Verify that when building the startup module response,
         * an exception from one module class will not break the entire
         * startup module response. See T152266.
+        *
+        * @covers ResourceLoader::makeModuleResponse
         */
        public function testMakeModuleResponseStartupError() {
                $rl = new EmptyResourceLoader();
index fbbcee5..4c5bab3 100644 (file)
@@ -185,7 +185,7 @@ class SearchEnginePrefixTest extends MediaWikiLangTestCase {
        public function testSearch( array $case ) {
                $this->search->setLimitOffset( 3 );
                $results = $this->search->defaultPrefixSearch( $case['query'] );
-               $results = array_map( function( Title $t ) {
+               $results = array_map( function ( Title $t ) {
                        return $t->getPrefixedText();
                }, $results );
 
@@ -203,7 +203,7 @@ class SearchEnginePrefixTest extends MediaWikiLangTestCase {
        public function testSearchWithOffset( array $case ) {
                $this->search->setLimitOffset( 3, 1 );
                $results = $this->search->defaultPrefixSearch( $case['query'] );
-               $results = array_map( function( Title $t ) {
+               $results = array_map( function ( Title $t ) {
                        return $t->getPrefixedText();
                }, $results );
 
@@ -349,7 +349,7 @@ class SearchEnginePrefixTest extends MediaWikiLangTestCase {
                $search->setLimitOffset( 3 );
                $results = $search->completionSearch( $case['query'] );
 
-               $results = $results->map( function( SearchSuggestion $s ) {
+               $results = $results->map( function ( SearchSuggestion $s ) {
                        return $s->getText();
                } );
 
index 60559fc..28c69fa 100644 (file)
@@ -43,7 +43,7 @@ class SearchSuggestionSetTest extends \PHPUnit_Framework_TestCase {
                $this->assertEquals( 3, $set->getBestScore() );
                $this->assertEquals( 1, $suggestion->getScore() );
 
-               $scores = $set->map( function( $s ) {
+               $scores = $set->map( function ( $s ) {
                        return $s->getScore();
                } );
                $sorted = $scores;
@@ -80,7 +80,7 @@ class SearchSuggestionSetTest extends \PHPUnit_Framework_TestCase {
                $this->assertEquals( 6, $set->getBestScore() );
                $this->assertEquals( 6, $suggestion->getScore() );
 
-               $scores = $set->map( function( $s ) {
+               $scores = $set->map( function ( $s ) {
                        return $s->getScore();
                } );
                $sorted = $scores;
index 7e37907..adf95e6 100644 (file)
@@ -101,7 +101,7 @@ class CachingSiteStoreTest extends MediaWikiTestCase {
 
                $dbSiteStore->expects( $this->any() )
                        ->method( 'getSites' )
-                       ->will( $this->returnCallback( function() {
+                       ->will( $this->returnCallback( function () {
                                $siteList = new SiteList();
                                $siteList->setSite( $this->getTestSite() );
 
index 4e9d826..94924ee 100644 (file)
@@ -183,7 +183,7 @@ class SpecialSearchTest extends MediaWikiTestCase {
                $rewrittenQuery,
                array $resultTitles
        ) {
-               $results = array_map( function( $title ) {
+               $results = array_map( function ( $title ) {
                        return SearchResult::newFromTitle( $title );
                }, $resultTitles );
 
index 6506d58..017e97d 100644 (file)
@@ -36,7 +36,7 @@ class BatchRowUpdateTest extends MediaWikiTestCase {
                $batchSize = 2;
                $reader = new BatchRowIterator( $db, 'some_table', 'id_field', $batchSize );
 
-               $response = $this->genSelectResult( $batchSize, /*numRows*/ 5, function() {
+               $response = $this->genSelectResult( $batchSize, /*numRows*/ 5, function () {
                        static $i = 0;
                        return [ 'id_field' => ++$i ];
                } );
@@ -171,7 +171,7 @@ class BatchRowUpdateTest extends MediaWikiTestCase {
        public function testReaderSelectConditionsMultiplePrimaryKeys(
                $message, $expectedSecondIteration, $primaryKeys, $batchSize = 3
        ) {
-               $results = $this->genSelectResult( $batchSize, $batchSize * 3, function() {
+               $results = $this->genSelectResult( $batchSize, $batchSize * 3, function () {
                        static $i = 0, $j = 100, $k = 1000;
                        return [ 'id_field' => ++$i, 'foo' => ++$j, 'bar' => ++$k ];
                } );
@@ -204,7 +204,7 @@ class BatchRowUpdateTest extends MediaWikiTestCase {
                        ->will( $this->consecutivelyReturnFromSelect( $retvals ) );
                $db->expects( $this->any() )
                        ->method( 'addQuotes' )
-                       ->will( $this->returnCallback( function( $value ) {
+                       ->will( $this->returnCallback( function ( $value ) {
                                return "'$value'"; // not real quoting: doesn't matter in test
                        } ) );
 
index e801e8c..5212ee9 100644 (file)
                                { name: 'filter8', label: 'group3filter8-label', description: 'group3filter8-desc' },
                                { name: 'filter9', label: 'group3filter9-label', description: 'group3filter9-desc' }
                        ]
+               }, {
+                       name: 'group4',
+                       type: 'single_option',
+                       default: 'option1',
+                       filters: [
+                               { name: 'option1', label: 'group4option1-label', description: 'group4option1-desc' },
+                               { name: 'option2', label: 'group4option2-label', description: 'group4option2-desc' },
+                               { name: 'option3', label: 'group4option3-label', description: 'group4option3-desc' }
+                       ]
                } ],
                viewsDefinition = {
                        namespaces: {
@@ -81,6 +90,7 @@
                        filter5: '1',
                        filter6: '0',
                        group3: 'filter8',
+                       group4: 'option1',
                        namespace: ''
                },
                baseParamRepresentation = {
                        filter5: '0',
                        filter6: '0',
                        group3: '',
+                       group4: '',
                        namespace: ''
                },
                baseFilterRepresentation = {
                        group3__filter7: false,
                        group3__filter8: false,
                        group3__filter9: false,
+                       group4__option1: false,
+                       group4__option2: false,
+                       group4__option3: false,
                        namespace__0: false,
                        namespace__1: false,
                        namespace__2: false,
                        group3__filter7: { selected: false, conflicted: false, included: false },
                        group3__filter8: { selected: false, conflicted: false, included: false },
                        group3__filter9: { selected: false, conflicted: false, included: false },
+                       group4__option1: { selected: false, conflicted: false, included: false },
+                       group4__option2: { selected: false, conflicted: false, included: false },
+                       group4__option3: { selected: false, conflicted: false, included: false },
                        namespace__0: { selected: false, conflicted: false, included: false },
                        namespace__1: { selected: false, conflicted: false, included: false },
                        namespace__2: { selected: false, conflicted: false, included: false },
                        } ),
                        'All filters selected in "string_option" group returns \'all\'.'
                );
+
+               // Reset
+               model = new mw.rcfilters.dm.FiltersViewModel();
+               model.initializeFilters( filterDefinition, viewsDefinition );
+
+               // Select an option from single_option group
+               model.toggleFiltersSelected( {
+                       group4__option2: true
+               } );
+               // All filters of the group are selected == this is the same as not selecting any
+               assert.deepEqual(
+                       model.getParametersFromFilters(),
+                       $.extend( true, {}, baseParamRepresentation, {
+                               group4: 'option2'
+                       } ),
+                       'Selecting an option from "single_option" group returns that option as a value.'
+               );
+
+               // Select a different option from single_option group
+               model.toggleFiltersSelected( {
+                       group4__option3: true
+               } );
+               // All filters of the group are selected == this is the same as not selecting any
+               assert.deepEqual(
+                       model.getParametersFromFilters(),
+                       $.extend( true, {}, baseParamRepresentation, {
+                               group4: 'option3'
+                       } ),
+                       'Selecting a different option from "single_option" group changes the selection.'
+               );
        } );
 
        QUnit.test( 'getParametersFromFilters (custom object)', function ( assert ) {
                                        { name: 'filter8', label: 'Hide filter 8', description: '' },
                                        { name: 'filter9', label: 'Hide filter 9', description: '' }
                                ]
+                       }, {
+                               name: 'group4',
+                               title: 'Group 4',
+                               type: 'single_option',
+                               filters: [
+                                       { name: 'filter10', label: 'Hide filter 10', description: '' },
+                                       { name: 'filter11', label: 'Hide filter 11', description: '' },
+                                       { name: 'filter12', label: 'Hide filter 12', description: '' }
+                               ]
                        } ],
+                       baseResult = {
+                               hidefilter1: '0',
+                               hidefilter2: '0',
+                               hidefilter3: '0',
+                               hidefilter4: '0',
+                               hidefilter5: '0',
+                               hidefilter6: '0',
+                               group3: '',
+                               group4: ''
+                       },
                        cases = [
                                {
                                        // This is mocking the cases above, both
                                                group3__filter8: true,
                                                group3__filter9: false
                                        },
-                                       expected: {
+                                       expected: $.extend( true, {}, baseResult, {
                                                // Group 1 (two selected, the others are true)
-                                               hidefilter1: '0',
-                                               hidefilter2: '0',
                                                hidefilter3: '1',
-                                               // Group 2 (nothing is selected, all false)
-                                               hidefilter4: '0',
-                                               hidefilter5: '0',
-                                               hidefilter6: '0',
+                                               // Group 3 (two selected)
                                                group3: 'filter7,filter8'
-                                       },
+                                       } ),
                                        msg: 'Given an explicit (complete) filter state object, the result is the same as if the object given represented the model state.'
                                },
                                {
                                        input: {
                                                group1__hidefilter1: 1
                                        },
-                                       expected: {
+                                       expected: $.extend( true, {}, baseResult, {
                                                // Group 1 (one selected, the others are true)
-                                               hidefilter1: '0',
                                                hidefilter2: '1',
-                                               hidefilter3: '1',
-                                               // Group 2 (nothing is selected, all false)
-                                               hidefilter4: '0',
-                                               hidefilter5: '0',
-                                               hidefilter6: '0',
-                                               group3: ''
-                                       },
+                                               hidefilter3: '1'
+                                       } ),
                                        msg: 'Given an explicit (incomplete) filter state object, the result is the same as if the object give represented the model state.'
                                },
                                {
-                                       input: {},
-                                       expected: {
-                                               hidefilter1: '0',
-                                               hidefilter2: '0',
-                                               hidefilter3: '0',
-                                               hidefilter4: '0',
-                                               hidefilter5: '0',
-                                               hidefilter6: '0',
-                                               group3: ''
+                                       input: {
+                                               group4__filter10: true
                                        },
+                                       expected: $.extend( true, {}, baseResult, {
+                                               group4: 'filter10'
+                                       } ),
+                                       msg: 'Given a single value for "single_option" that option is represented in the result.'
+                               },
+                               {
+                                       input: {
+                                               group4__filter10: true,
+                                               group4__filter11: true
+                                       },
+                                       expected: $.extend( true, {}, baseResult, {
+                                               group4: 'filter10'
+                                       } ),
+                                       msg: 'Given more than one true value for "single_option" (which should not happen!) only the first value counts, and the second is ignored.'
+                               },
+                               {
+                                       input: {},
+                                       expected: baseResult,
                                        msg: 'Given an explicit empty object, the result is all filters set to their falsey unselected value.'
                                }
                        ];
                        } ),
                        'A \'string_options\' parameter containing an invalid value, results in the invalid value ignored and the valid corresponding filters checked.'
                );
+
+               model.toggleFiltersSelected(
+                       model.getFiltersFromParameters( {
+                               group4: 'option1'
+                       } )
+               );
+               assert.deepEqual(
+                       model.getSelectedState(),
+                       $.extend( {}, baseFilterRepresentation, {
+                               group4__option1: true
+                       } ),
+                       'A \'single_option\' parameter reflects a single selected value.'
+               );
+
+               assert.deepEqual(
+                       model.getFiltersFromParameters( {
+                               group4: 'option1,option2'
+                       } ),
+                       baseFilterRepresentation,
+                       'An invalid \'single_option\' parameter is ignored.'
+               );
+
+               // Change to one value
+               model.toggleFiltersSelected(
+                       model.getFiltersFromParameters( {
+                               group4: 'option1'
+                       } )
+               );
+               // Change again to another value
+               model.toggleFiltersSelected(
+                       model.getFiltersFromParameters( {
+                               group4: 'option2'
+                       } )
+               );
+               assert.deepEqual(
+                       model.getSelectedState(),
+                       $.extend( {}, baseFilterRepresentation, {
+                               group4__option2: true
+                       } ),
+                       'A \'single_option\' parameter always reflects the latest selected value.'
+               );
        } );
 
        QUnit.test( 'sanitizeStringOptionGroup', function ( assert ) {